Page 2 of 3

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 8:51 am
by Roland_Yonaba
Implementing OOP with closures is a nice, simple and elegant method though. I am definitely not advocating against, but for the sake of discussion, I would just like to point out it seems this approach involves more memory consumption.
Steve Litt also discussed the topic here.
I would love to hear your own thoughts about that.

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 7:16 pm
by Kibita
Take a look at this on reddit: https://www.reddit.com/r/love2d/comment ... sses_work/
The user imaginaryrobots shows how he makes his classes. He's doing right? Because it seems good to me (the code itself)

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 8:11 pm
by rmcode
Roland_Yonaba wrote:I would love to hear your own thoughts about that.
I am using the Closure Based Approach in all of my projects and so far I didn't have any problems with it. Obviously I don't have a comparison though, but with the metatable approach each object uses two tables which also take up memory whereas an object with the closure based approach only uses one (even if you use extensive inheritance).

This is how easily you can implement inheritance:

Code: Select all

local ParentClass = {};

function ParentClass.new()
    local self = {};

    return self;
end

return ParentClass;

Code: Select all

local ChildClass = {};

function ChildClass.new()
    local self = ParentClass.new(); -- Use the table from the parent class.

    return self;
end

return ChildClass;

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 8:14 pm
by Inny
Lua is itself inconsistent in how classes should be built. Strings have a hidden metatable that points via __index at the string table. However files have a hidden metatable that points at itself, which doesn't exist under _G anywhere.

Generally speaking, the method in Pil where you have Class.__index = Class is the closest to official and probably the most compatible between all of the libraries that would use classes. In the reddit thread you mention, imaginaryrobot's is this method. I tend to not like to assign the self.__index = self bit, but rather would write Queue.__index = Queue where the class is first created (the line after local Queue = {}), mostly because it's a good idea to design classes to not change anymore after you've returned their class object from the module. I'll show you my method and explain everything:

Code: Select all

local Foo = {}           -- create class object
Foo.__index = Foo   -- only change an object while we're still building it.

function Foo:new( ... )
  local inst = setmetatable({}, self)    -- self in this context *could* be Foo, but could be a subclass
  inst:init(...)                                  -- call an init function in case there's a Subclass doing an override
  return inst
end

function Foo:init(your, code, here)
  -- self in this context is the instance
end

return Foo
As mentioned, this enables subclasses

Code: Select all

local Foo = require('foo')
local Bar = {}
for k, v in pairs(Foo) do Bar[k] = v end     -- subclass via copying
-- Alternatively, you can subclass by Making Bar's metatable be Foo

Bar.__index = Bar  -- And correctly point Bar's instances as the subclass.

function Bar:init(other, code, here)
  Foo.init(self, parameters)
  -- other initialization
end

return Bar

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 11:12 pm
by bobbyjones
rmcode wrote:
Roland_Yonaba wrote:I would love to hear your own thoughts about that.
I am using the Closure Based Approach in all of my projects and so far I didn't have any problems with it. Obviously I don't have a comparison though, but with the metatable approach each object uses two tables which also take up memory whereas an object with the closure based approach only uses one (even if you use extensive inheritance).
How does each object use 2 tables? Metatables are one table shared between all objects.

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 11:16 pm
by rmcode
Ah yes ... my bad. I just meant that the difference in memory consumption is probably negligible.

Re: Create a class without external libraries

Posted: Sat Feb 13, 2016 11:34 pm
by bobbyjones
rmcode wrote:Ah yes ... my bad. I just meant that the difference in memory consumption is probably negligible.
If you have a couple hundred objects I believe that the metatables method would probably be much more efficient on terms of memory. Idk about in performance tho.

Re: Create a class without external libraries

Posted: Sun Feb 14, 2016 12:16 am
by Kibita
Inny wrote:Lua is itself inconsistent in how classes should be built. Strings have a hidden metatable that points via __index at the string table. However files have a hidden metatable that points at itself, which doesn't exist under _G anywhere.

Generally speaking, the method in Pil where you have Class.__index = Class is the closest to official and probably the most compatible between all of the libraries that would use classes. In the reddit thread you mention, imaginaryrobot's is this method. I tend to not like to assign the self.__index = self bit, but rather would write Queue.__index = Queue where the class is first created (the line after local Queue = {}), mostly because it's a good idea to design classes to not change anymore after you've returned their class object from the module. I'll show you my method and explain everything:
[/code]
It's necessary to use the init function?

Re: Create a class without external libraries

Posted: Sun Feb 14, 2016 12:42 am
by s-ol
rmcode wrote:Ah yes ... my bad. I just meant that the difference in memory consumption is probably negligible.
It is not if you have many objects because your approach creates a new set of member (and private!) functions for every object. So if you have 5 methods and 4 private helper functions and you create 10 instances you have 90 different functions an 9 tables in memory. With metatables you have 9 functions and 10 tables.

That is unless luajit can optimize this to keep just one instance of each function with a different closure, but I'm not sure whether that's possible and it would still make 9 functions, 90 closures and 9 tables.

Also it you want to do operator overloading, read only attributes, fallbacks or something of the like you need metatables anyway.

All that said, I do like the idea of the closure-way, but it nearly makes the table obsolete; you could have all the attributes live in the closure too and just pass around the methods.

Oh - and why do you need the colon syntax with the closure approach? It works 100% the same if you just leave it out, the functions inherit the 'self' upvalue from the constructor.

Re: Create a class without external libraries

Posted: Sun Feb 14, 2016 1:00 am
by rmcode
S0lll0s wrote:Oh - and why do you need the colon syntax with the closure approach? It works 100% the same if you just leave it out, the functions inherit the 'self' upvalue from the constructor.
It's just my own flavor:

Code: Select all

Class.function()
object:method()
Easier to read IMO.