Page 2 of 2
Re: ClosureClass
Posted: Sat Mar 12, 2011 10:36 pm
by BlackBulletIV
kikito wrote:BlackBulletIV wrote:Indeed, this is one big problem with closures, instances won't respond if you modify the class, which is a shame.
Are you sure this is a problem due to closure usage? My gut tells me there must be a way to implement indirection with them too.
BlackBulletIV wrote:I'm not sure what you're talking about by copying methods directly to instances. If you're talking about the code the copies stuff from superclass to subclass, that's for inheriting class methods and attributes (and also modules).
I was talking about
this code inside _new (pasting below for reference)
Code: Select all
for _, m in pairs(cls.__modules) do
for name, func in pairs(m) do
if name ~= 'included' then
self[name] = function(...) return func(self, ...) end -- get rid of self for the outside world
end
end
end
I'm not sure of what it does - maybe getting rid of the need of using : instead of . ? But then, why doing that only with module methods?
BlackBulletIV wrote:I'm guessing metamethods are copied, I'm not quite sure how it works in MiddleClass (don't you just define an instance function). Anyway, metamethods are yet to be handled.
Metamethods are a bit of a pain on lua when dealing with inheritance. The problem is that Lua doesn't want to use metatables in order to get metamethods: a table
must have a __tostring metamethod on its metatable; if its "parent" (the metatable pointed by __index) has a __tostring, Lua doesn't care.
On middleclass I handle this by creating a set of "default metamethods" on every new class. These methods "point" to the methods on the superclass. And if there's no parent, they throw an error, just like a regular method would.
I'm sure there is a way, but it would most likely involve some hardcore table trickery, which I'd have to rack my brain for awhile to figure out.
Oh that code copies module functions from the class into the instance. To maintain consistency it wraps the functions to remove the need of a self parameter. As explained in the recently added README, module functions must have a self parameter because they're not declared inside the initialisation function (the closure), therefore they need a reference to self.
Hmmmm, not quite sure whether I totally understand what you're talking about with metamethods. But I have seen how you make a default implementation which throws an error. But anyway, metamethods aren't implemented yet, they might be soon.
All in all, I think the closure method is not a very good fit for a full OOP system in Lua. But still, I love the style.
Re: ClosureClass
Posted: Sat Mar 12, 2011 10:54 pm
by bartbes
You could get the metatable a metatable. Inception.
Re: ClosureClass
Posted: Sun Mar 13, 2011 12:35 am
by BlackBulletIV
Which problem are you referring to by that?
Re: ClosureClass
Posted: Sun Mar 13, 2011 4:03 am
by tentus
bartbes wrote:You could get the metatable a metatable. Inception.
I just rewatched that tonight with my younger bro, who missed it when it came out. Enjoyable film.
Re: ClosureClass
Posted: Sun Mar 13, 2011 4:44 am
by BlackBulletIV
Oh, you're talking about a movie. Ok.
Re: ClosureClass
Posted: Sun Mar 13, 2011 9:17 am
by bartbes
It's a real option though, getting a metatable with an __index metafield set to the parent's metatable.
Re: ClosureClass
Posted: Mon Mar 14, 2011 1:44 am
by appleide
Tangent.
Recently, I've started to use classes implemented by the following code.
Code: Select all
function class(parent)
local new = {}
for k, v in pairs(parent or {init=function() end}) do
new[k] = v
end
new.__super, new.__index = parent, new
return setmetatable(new, {__call = function(t , ...)
local instance=setmetatable({__class = new}, new);
new.init(instance, ...)
return instance
end})
end
Child classes are copies of parent classes.
To instantiate a class, simply call it. e.g. local myvector = vector(x, y)
Classes are the instances metatables, so you can write a method class:__add to overload the + operator.
Code: Select all
style = class()
--- Initiates a style instance.
-- @param tags A string of whitespace separated tags.
-- @param styles A table of key-value style attributes.
function style:init(tags, styles)
self.tags = sorttags(tags)
self.styles = {}
self.owner = nil
for k, v in pairs(styles) do
self.styles[k] = v
end
self:compute()
end
--- Compute styles. E.g. borderleftwidth and borderwidth
function style:compute()
local this = self.styles
-- ...more code... --
end
Re: ClosureClass
Posted: Mon Mar 14, 2011 3:27 am
by BlackBulletIV
That looks like a largely simplified version of MiddleClass to be (in the result anyway). The big thing it lacks, which I would not like to be without, is mixins.
Re: ClosureClass
Posted: Mon Mar 14, 2011 12:22 pm
by kikito
Robin wrote:kikito wrote:Metamethods are a bit of a pain on lua when dealing with inheritance. The problem is that Lua doesn't want to use metatables in order to get metamethods: a table must have a __tostring metamethod on its metatable; if its "parent" (the metatable pointed by __index) has a __tostring, Lua doesn't care.
That is because
Code: Select all
mt.__index = t -- where mt is the metatable of some other table and t is yet another table
is really a shortcut for
Code: Select all
mt.__index = function (table, key) return t[key] end
Thus
t is really not a "parent" of whatever uses
mt as metatable, it's just a place to get values for missing keys from.
I know that. The problem is that Lua uses something equivalent to
rawget(getmetatable(t), '__tostring') instead of using
t.__tostring to get a metamethod. They are not "looked up through __index". So the only option left is creating "fake" metamethods that do that extra bit of work.