[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: metatables reprise
- From: Gunnar Zötl <gz@...>
- Date: Tue, 14 Jan 2003 16:42:33 +0100
Hi there,
sorry, my mail address was disconnected for a few days :-(
Regarding Wins reply to my previous query about metatables (not)
having metatables, that was very informative, thanks. However, it did
not really help with the problem at hand. A quick refresh:
I have written a (simple?) class system for lua, with inheritance and
stuff. It works with two sets of metatables: classes have a metatable
that links then to their base classes (for method-lookup and such),
and instances have a metatable that links them to their class.
All of this is working neatly, and just took about 9KB of code,
including heavy comments detailing the usage. I fully agree with the
lua team that having meta-features in a scripting language is much
more useful that a bunch of features.
As a next step I intended to add a facility to implement the meta-
methods (such as __sub, __add and so forth) as methods within my
classes. My first attempt at this was to add "forwarders" for those
methods to the metatable that is attached to the instances, which
would then check wether the class defines that method, and calls it.
This works fine, except for one thing. Consider this:
ca = Class { x = 1 }
cb = Class { x = 2,
__add = function(op1, op2) return op1.x + op2.x end
}
a = ca:new()
b = cb:new()
with these settings, b+a works, but a+b does not. This is because the
instances metatable for a does define the __add method (forwarder),
but the class does not. Lua just sees that there is an __add
metamethod in a's metatable. In the b+a case, b's __add meta-method
calls the method defined within cb, and everything is fine.
My current solution for this problem is to install a __newindex
handler in the classes metatable, which will add a redirector to the
instances metatable for every meta-method that is defined within the
class. Now everything works fine, but at a cost:
- when extending a class with a new class, all metamethods from the
base class have to be propagated to the new class' instance table.
- obviously, when setting some metamethod of a class to nil after the
class with that method has been declared, this change can not be
detected, and we are back to the problem detailed above with ca and
cb. However, as this case should be rare, I think I can live with
this.
Maybe I should put the code somewhere, in case somebody wants to look
at it in order to understand what I'm talking about ;-) It is
currently about 13KB, including usage info.
Back to the problem: What I would really like to have is a mechanism
whereby a metatable can redirect calls to metamethods in a way that
they actually appear as undefined when they are not defined in
whatever place they are redirected to. Does anyone have an idea how I
could achieve this?
rgds,
Gunnar