6

我无法理解为什么__index这些示例之间的元方法的行为存在差异:

A = { __index = A }   
function A:speak()
    print("I'm an A")
end
An_A = setmetatable({},A)
An_A:speak()

将引发以下错误:lua: l.lua:8: attempt to call method 'speak' (a nil value)

同时

B = { __index = function(t,key)  return B[key] end }
function B:speak()
    print("I'm an B")
end
An_B = setmetatable({},B)
An_B:speak()

将按预期执行,输出I'm an B.


为了理解为什么会这样,我阅读了 PiL 的这一部分。它指出:

__index 元方法用于继承是如此普遍,以至于 Lua 提供了一个快捷方式。尽管有这个名字,__index 元方法不需要是一个函数:它可以是一个表,而是。当它是一个函数时,Lua 用表和缺失的键作为它的参数来调用它。当它是一个表时,Lua 会重做对该表的访问。

我对此的理解是,在涉及“A”的片段中,__index = A导致在表中完成访问A(根据上述引用的加粗部分)。如果是这种情况,我不明白为什么"speak"找不到与密钥关联的功能。为了尝试解决这个问题,我决定在代码片段中实现函数方法,它返回与inB关联的值,并且它起作用了。肯定和 (改编自)具有相同的效果。keyB__index = AB__index = function(t,key) return A[key] end

任何澄清将不胜感激。

4

1 回答 1

9

您的第一个示例中发生的是A.__index == nil. 当您在这里的第一行创建“A”时:

A = { __index = A }

赋值“A”的右侧计算结果为,nil因为此时它还不存在。结果,稍后当您在此处设置元表时:

An_A = setmetatable({},A)

它实际上最终会做类似这样的事情:

An_A = setmetatable({}, {__index = nil} )

为了让它以你想要的方式工作,你必须确保__indexis not nil。例如在建表后赋值:

A = {}
A.__index = A

function A:speak()
  print("I'm an A")
end
An_A = setmetatable({},A)
An_A:speak()              --> outputs I'm an A
于 2013-05-11T02:49:15.880 回答