WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Dealing with templates and OOP (https://www.wowinterface.com/forums/showthread.php?t=59783)

Benalish 02-05-24 04:32 PM

Dealing with templates and OOP
 
This is the first time I try to apply OOP in Lua. My goal is to create a template as if it were an object, without using the mixin.

XML code:

Code:

<Frame name="TemplateListViewTemplate" virtual="true">               
        <Scripts>
                <OnLoad>
                        self = LibUnitScanListView:New(self)
                </OnLoad>
        </Scripts>
</Frame>

Lua code:

Lua Code:
  1. LibListView = {}
  2.  
  3. function LibListView:New(self)
  4.        
  5.         local listviewmt = {
  6.             buttons  = {},
  7.             data = {},
  8.             --more methods and functions
  9.             SetWidgetScript = function(words) print(words) end,
  10.         }
  11.         setmetatable(self, { __index = setmetatable(listviewmt, getmetatable(self)) })
  12. end

If I write

Lua Code:
  1. self = LibListView:New(self)
inside <OnLoasd> tag the code works fine. At this point, I would like to make sure that the class is created without passing self as a parameter: in short, using the wording
Lua Code:
  1. listview = LibListView:New()
to make the code more elegant.
I tried to not put self in the signature, just leaving it without any params:
Lua Code:
  1. function LibListView:New()
At this point an error emerges:


Lua Code:
  1. listview = CreateFrame("Frame","listview",UIParent,"TemplateListViewTemplate")
  2. listview:SetSize(150, 100)
  3. listview:SetPoint("TOPLEFT",50,-75)
  4. listview:SetWidgetScript("Hello World")
returns this error:

attempt to call method 'SetWidgetScript' (a nil value)

Can you help me?

SDPhantom 02-05-24 08:31 PM

The way Lua handles obj.method() vs obj:method() is simple, but not straightforward.
When calling a function, obj:method(...) is the same as obj.method(obj,...).
When defining a function, obj:method(...) is the same as obj.method(self,...).

Lua will handle mixing these syntaxes as long as you take the above rule in mind.
If you call obj.method(frame), a function defined as obj:method() will receive frame and put it in self.

One way or another, you need a reference to your frame to work on it. The WoW API doesn't set any globals when a frame script runs.



The way I would implement your code with this in mind and make room for easier expansion:
Lua Code:
  1. --  __mode defines whether (k)eys and/or (v)alues are released to the GC if this table is the only remaining reference to them (in either case, the entire table entry is removed)
  2. --  Frames can't be garbage collected, but it's still good practice for memory management if you're storing external objects
  3. local OriginalMeta=setmetatable({},{__mode="kv"});
  4.  
  5. --  ListView frame metatable set to refer to its original metatable as a fallback (Stored by LibListView:New())
  6. local ListViewMeta={__index=setmetatable({},{__index=function(obj,key) return OriginalMeta[obj][key]; end})};
  7.  
  8. LibListView={};
  9. function LibListView:New()--    self is our new frame (call as LibListView.New(frame))
  10.     assert(OriginalMeta[self]==nil,"Already attached to frame");
  11.     OriginalMeta[self]=getmetatable(self);--    Store original metatable as a fallback
  12.     setmetatable(self,ListViewMeta);--  Set new metatable
  13.  
  14.     self:Initialize();
  15. end
  16.  
  17. --  Frame methods injected by our library
  18. function ListViewMeta.__index:Initialize()
  19. --  Initialize instanced data and store to frame
  20.     self.Buttons={};
  21.     self.Data={};
  22. end
  23.  
  24. function ListViewMeta.__index:SetWidgetScript(something)
  25.     print(something);
  26. end

OnLoad Handler:
Code:

LibListView.New(self)
Test Script:
Lua Code:
  1. local listview = CreateFrame("Frame","listview",UIParent,"TemplateListViewTemplate")
  2. listview:SetSize(150, 100)
  3. listview:SetPoint("TOPLEFT",50,-75)
  4. listview:SetWidgetScript("Hello World")



One major change was to separate your static functions and instanced data. The frame methods were moved to their own metatable and are injected into the frame. As the frame is basically a table itself, data values are written directly into it.


All times are GMT -6. The time now is 03:46 PM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI