通过__index进行元方式查找?

时间:2010-07-18 15:23:35

标签: lua metaprogramming lua-table

我已经实现了自己的班级系统,我遇到了__tostring的问题;我怀疑其他metamethods也会发生类似的问题,但我还没有尝试过。

(简要介绍:每个类都有__classDict属性,包含所有方法。它用作类实例'__index。同时,__ classDict的__index是超类'__classDict,因此可以自动查找超类中的方法。)

我希望在所有实例中都有“默认的tostring”行为。但它不起作用:“tostring”行为不会正确地“传播”通过子类。

我已完成此测试,例证我的问题:

mt1 = {__tostring=function(x) return x.name or "no name" end }
mt2 = {}
setmetatable(mt2, {__index=mt1})
x = {name='x'}
y = {name='y'}
setmetatable(x, mt1)
setmetatable(y, mt2)
print(x) -- prints "x"
print(mt2.__tostring(y)) -- prints "y"
print(y) -- prints "table: 0x9e84c18" !!

我宁愿让最后一行打印“y”。

Lua的“to_String”行为必须使用等效的

rawget(instance.class.__classDict, '__tostring')

而不是相当于

instance.class.__classDict.__tostring

我怀疑所有metamethods都会发生同样的事情; rawget - 使用等效操作。

我想我可以做的一件事就是在我进行子类化时复制所有的元方法(上面的例子中的等价物将是mt2.__tostring = mt1.__tostring),但这有点不雅。

有没有人为这类问题而战?您的解决方案在哪里?

4 个答案:

答案 0 :(得分:3)

  

我怀疑所有metamethods都会发生同样的事情;使用rawget等效操作。

这是正确的。 来自lua手册:

  

...应该被理解为rawget(getmetatable(obj) or {}, event)。也就是说,对元方法的访问不会调用其他元方法,并且对没有元表的对象的访问不会失败(它只会导致nil)。

通常每个类都有自己的元表,并将所有对函数的引用复制到其中。 也就是说,mt2.__tostring = mt1.__tosting

答案 1 :(得分:1)

答案 2 :(得分:0)

根据我对Lua 5.1的经验,使用rawget()在元数据中查找元方法,这就是必须将对函数的引用复制到您创建的每个类表中的原因。

答案 3 :(得分:-1)

请参阅Lua Users Wiki上的Inheritance Tutorial