32 lines of goodness, yet another OO lib
- ishkabible
- Party member
- Posts: 241
- Joined: Sat Oct 23, 2010 7:34 pm
- Location: Kansas USA
Re: 32 lines of goodness, yet another OO lib
what he said
- Robin
- The Omniscient
- Posts: 6506
- Joined: Fri Feb 20, 2009 4:29 pm
- Location: The Netherlands
- Contact:
Re: 32 lines of goodness, yet another OO lib
I like to dispute the "goodness" of this library.
It does not actually work.
As long as you don't use :extends(), it's fine (as far as I can tell), but when you do, all hell breaks loose.
This line. This line is the source of most misery. You see, when you create an instance of the subclass and try to access a property that doesn't exist, this happens:
This is more fucked up than you might think, by the way: think of the implications for multiple subclasses:
Actually, it is even worse. The last class passed to :extends would be the "parent" of every class existing now and to be made later, even itself. Luckily, we don't have to worry about that, since it doesn't work either way.
That's not goodness, this is just plain wrong.
This works:
EDIT: it works, but it is still wrong. Look closely at the behavior of __members__ for subclasses.
Replacing the first line of define byshould do it.
It does not actually work.
As long as you don't use :extends(), it's fine (as far as I can tell), but when you do, all hell breaks loose.
Code: Select all
setmetatable(mt_class, {__index = parent})
Code: Select all
instance.blah -- doesn't exist!
subclass.blah -- doesn't exist!
mt_class.blah -- doesn't exist!
superclass.blah -- doesn't exist!
mt_class.blah -- doesn't exist!
Error, stuck in a loop. (Lua sez "loop in gettable".)
Code: Select all
class "A"{}
class "B"{}
class "C":extends(A){}
class "D":extends(B){} -- surprise, C is now a subclass of B instead of A!
That's not goodness, this is just plain wrong.
This works:
Code: Select all
local mt_class = {}
local function define(class, members)
class.__members__ = class.__members__ or {}
for k, v in pairs(members) do
class.__members__[k] = v
end
function class:new(...)
local newvalue = {}
for k, v in pairs(class.__members__) do
newvalue[k] = v
end
setmetatable(newvalue, {__index = class})
if newvalue.__init then
newvalue:__init(...)
end
return newvalue
end
end
function mt_class:extends(parent)
self.super = parent
setmetatable(self, {__index = parent, __call = define})
parent.__members__ = parent.__members__ or {}
return self
end
function class(name)
local newclass = {}
_G[name] = newclass
return setmetatable(newclass, {__index = mt_class, __call = define})
end
Replacing the first line of define by
Code: Select all
class.__members__ = {}
if class.super then
for k, v in pairs(class.super.__members__) do
class.__members__[k] = v
end
end
Help us help you: attach a .love.
- ishkabible
- Party member
- Posts: 241
- Joined: Sat Oct 23, 2010 7:34 pm
- Location: Kansas USA
Re: 32 lines of goodness, yet another OO lib
hmm, i should have tested further, this is embarrassing.
Re: 32 lines of goodness, yet another OO lib
I know this post is old, and I know there are better libraries out there, but I like the looks of this one, as it looks really close to what I'm looking for.
Does this fix work as advertised?
Does this fix work as advertised?
- Robin
- The Omniscient
- Posts: 6506
- Joined: Fri Feb 20, 2009 4:29 pm
- Location: The Netherlands
- Contact:
Re: 32 lines of goodness, yet another OO lib
I'm not sure. I wrote the fix, but I'm not maintaining this "library".
May I suggest Slither as an alternative?
May I suggest Slither as an alternative?
Help us help you: attach a .love.
- ishkabible
- Party member
- Posts: 241
- Joined: Sat Oct 23, 2010 7:34 pm
- Location: Kansas USA
Re: 32 lines of goodness, yet another OO lib
Robins fixes work, I wrote this as a spur of the moment thing after I saw someone else do it and didn't give it much other consideration(e.g. it's not being maintained). I did it badly as robin pointed out. If you use this lib and report any bugs I'll see what I can do to fix them. Of course, Slither has a very similar(if not even more elegant) syntax and is probably more stable. You might be better off with it instead.
Re: 32 lines of goodness, yet another OO lib
I can assure you that I prefer the way that you've set up in these 32 lines
It's perfect for what I need, thank you.
It's perfect for what I need, thank you.
- ishkabible
- Party member
- Posts: 241
- Joined: Sat Oct 23, 2010 7:34 pm
- Location: Kansas USA
Re: 32 lines of goodness, yet another OO lib
1 possible thing that might happen; if you declare a default value as a table then change it in the instance it will change it for all other subsequent instances. basic rule of thumb is to not declare default values as tables. I'm working on an improved version that will fix this(and stay within 32 LOC of properly formatted code!)
Re: 32 lines of goodness, yet another OO lib
It'd be great if you could update it
- ishkabible
- Party member
- Posts: 241
- Joined: Sat Oct 23, 2010 7:34 pm
- Location: Kansas USA
Re: 32 lines of goodness, yet another OO lib
well I incorporated Robin's fixes but getting a deep copy in there is a bit tougher. here is Robin's fixes crammed into well formatted 32 lines. I'll work on deep copies of default values later.
Code: Select all
local mt_class = {}
function copy(tin)
local tout = {}
for k, v in pairs(tin) do
tout[k] = v
end
return tout
end
local function define(class, members)
class.members = copy(class.super and class.super.members or {})
for k, v in pairs(members) do
class.members[k] = v
end
function class.new(...)
local t = setmetatable(copy(class.members), {__index = class})
local blah = t.__init and t:__init(...)
return t
end
end
function mt_class:extends(parent)
self.super = parent
parent.members = parent.members or {}
return setmetatable(self, {__index = parent, __call = define})
end
function class(name)
_G[name] = {}
return setmetatable(_G[name], {__index = mt_class, __call = define})
end
Who is online
Users browsing this forum: Bing [Bot], Google [Bot] and 0 guests