Hen*_*nyH 6 lua metatable lua-table
我无法理解为什么__index这些示例之间的元方法行为存在差异:
A = { __index = A }
function A:speak()
print("I'm an A")
end
An_A = setmetatable({},A)
An_A:speak()
Run Code Online (Sandbox Code Playgroud)
会引发以下错误: 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()
Run Code Online (Sandbox Code Playgroud)
将按预期执行,输出I'm an B.
在试图理解为什么会这样的情况下,我阅读了PiL的这一部分.它指出:
使用__index元方法进行继承是如此常见,以至于Lua提供了一种快捷方式.尽管有名称,但__index元方法不需要是一个函数:它可以是一个表,而不是.当它是一个函数时,Lua用表和缺席键作为参数来调用它.当它是一个表时,Lua重做该表中的访问权限.
我对此的理解是,在涉及"A"的代码段中,__index = A导致访问在表中完成A(根据上面引用的加速分段).如果是这种情况,我不明白为什么"speak"找不到与密钥相关的功能.为了尝试修复此问题,我决定在B代码段中实现函数方法,该方法返回与keyin 关联的值B,并且它有效.当然__index = A和(改编自B)__index = function(t,key) return A[key] end具有相同的效果.
任何澄清将不胜感激.
你的第一个例子中发生了什么A.__index == nil.当你在第一行创建'A'时:
A = { __index = A }
Run Code Online (Sandbox Code Playgroud)
赋值'A'的右侧评估为,nil因为此时它尚不存在.因此,稍后在此处设置metatable时:
An_A = setmetatable({},A)
Run Code Online (Sandbox Code Playgroud)
它真的最终做了类似于此的事情:
An_A = setmetatable({}, {__index = nil} )
Run Code Online (Sandbox Code Playgroud)
为了让它以您想要的方式工作,您必须确保__index不是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
Run Code Online (Sandbox Code Playgroud)