如何使用(类似)__index 扩展 Lua 元表

以下会话展示了我正在尝试的内容。我必须在某些文档中误读了一些内容,(我认为)里面说元表中的 __index 项提供了一个默认值,当表中没有为该键提供一个项时。重点是,它在元表本身上不起作用,但我不知道为什么不行。在哪里的文档中解释了这一点,对于这种情况我该怎么办?

谢谢!

> a = {}
> b = {}
> setmetatable(a,b)
table: 0000000002631ae0
> c = { __tostring = function(x) return "X" end }
> setmetatable(b,{ __index=c })
table: 0000000002631560
>
> print(a)
table: 0000000002631ae0
> -- 我期望的是:X
> print(getmetatable(a).__tostring)
function: 0000000002633840
> print(tostring(a))
table: 0000000002631ae0
> -- 再一次,期望是 X
> print(getmetatable(a).__tostring(a))
X
>

这里还有另一个例子。

> a = {}
> b = {}
> setmetatable(a,b)
table: 0000000002631fe0
> c = { __add = function(x,y) return "X" end }
> setmetatable(b,{ __index=c })
table: 00000000026316a0
>
> print(a+a)
stdin:1: attempt to perform arithmetic on a table value (global 'a')
stack traceback:
        stdin:1: in main chunk
        [C]: in ?
>

所以这个问题不是特定于 print 和 tostring。当然,在实际情况中,我希望有很多不同的对象共享很多元表值,而不必每次都复制所有内容...

点赞
用户8621712
用户8621712

这是因为 __index 与像 tbl.var 这样的索引操作有关。Lua 不使用 __index 来获取其他元方法(如 __tostring)。

您使用了 print,它直接从元表调用 __tostring,而在这里不使用 __index

__index:索引访问操作表[key]

了解更多:https://www.lua.org/manual/5.4/manual.html#2.4

解决方案是将元表 cb 合并。

setmetatable(b,{ __tostring = c.__tostring })
print(b) -- X
2020-11-10 19:01:16