Create a class without external libraries

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: Create a class without external libraries

Post 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.
User avatar
Kibita
Prole
Posts: 31
Joined: Tue Dec 29, 2015 7:46 pm

Re: Create a class without external libraries

Post 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)
Last edited by Kibita on Sat Feb 13, 2016 9:04 pm, edited 1 time in total.
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: Create a class without external libraries

Post 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;
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Create a class without external libraries

Post 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
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: Create a class without external libraries

Post 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.
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: Create a class without external libraries

Post by rmcode »

Ah yes ... my bad. I just meant that the difference in memory consumption is probably negligible.
bobbyjones
Party member
Posts: 730
Joined: Sat Apr 26, 2014 7:46 pm

Re: Create a class without external libraries

Post 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.
User avatar
Kibita
Prole
Posts: 31
Joined: Tue Dec 29, 2015 7:46 pm

Re: Create a class without external libraries

Post 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?
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: Create a class without external libraries

Post 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.

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
rmcode
Party member
Posts: 454
Joined: Tue Jul 15, 2014 12:04 pm
Location: Germany
Contact:

Re: Create a class without external libraries

Post 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.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot], Semrush [Bot] and 3 guests