Lua/Luajit: 同时索引和命名方法?
Lua/Luajit: Indexing and named method at the same time?
Lua PIL and Luajit FFI tutorial 在元表中给出了 __index
的两种用法。
一个是像obj[123]这样的索引,例如
__index = function (self, k) return self._data+(k-self._lower)
另一种用法是定义命名方法,如教程中所述,
__index = { area = function(a) return a.x*a.x + a.y*a.y end, },
然后我们可以像obj:area()
.
那样进行函数调用
我可以同时进行这两项操作吗,例如,直接索引和命名方法?
对于 Lua 中特别有趣的代码,答案通常是更多元tables。
当您的 __index
元方法实际上是 table 时,Lua 只是对给定的 table 执行标准 table 访问。这意味着您可以在您的 metatable 上设置一个 metatable。然后你可以在这个 "meta-metatable".
上设置一个 __index 元方法
foo = function()
print("foo")
end
bar = function(_, key)
return function()
print(string.format("bar: %s", key))
end
end
mmt = { __index = bar }
mti = { foo = foo }
mt = { __index = mti }
t = {}
setmetatable(mti, mmt)
setmetatable(t, mt)
t.foo() -- prints: "foo"
t.bar() -- prints: "bar: bar"
t.baz() -- prints: "bar: baz"
这样,当您尝试访问两个 table 中都不存在的字段时,lua 将首先尝试访问顶级 table,后者将访问第一个 metatable 然后将在第二个 metatable.
中调用你的元方法
还有另一个可能更直接的答案:使用您的 __index
元方法检查另一个 table 的命名字段:
foo = function()
print("foo")
end
f = { foo = foo }
bar = function(_, key)
if f[key] then return f[key] end
return function()
print(string.format("bar: %s", key))
end
end
mt = { __index = bar }
t = {}
setmetatable(t, mt)
t.foo() -- prints: "foo"
t.bar() -- prints: "bar: bar"
t.baz() -- prints: "bar: baz"
在 Lua 5.3.
上测试
Lua PIL and Luajit FFI tutorial 在元表中给出了 __index
的两种用法。
一个是像obj[123]这样的索引,例如
__index = function (self, k) return self._data+(k-self._lower)
另一种用法是定义命名方法,如教程中所述,
__index = { area = function(a) return a.x*a.x + a.y*a.y end, },
然后我们可以像obj:area()
.
我可以同时进行这两项操作吗,例如,直接索引和命名方法?
对于 Lua 中特别有趣的代码,答案通常是更多元tables。
当您的 __index
元方法实际上是 table 时,Lua 只是对给定的 table 执行标准 table 访问。这意味着您可以在您的 metatable 上设置一个 metatable。然后你可以在这个 "meta-metatable".
foo = function()
print("foo")
end
bar = function(_, key)
return function()
print(string.format("bar: %s", key))
end
end
mmt = { __index = bar }
mti = { foo = foo }
mt = { __index = mti }
t = {}
setmetatable(mti, mmt)
setmetatable(t, mt)
t.foo() -- prints: "foo"
t.bar() -- prints: "bar: bar"
t.baz() -- prints: "bar: baz"
这样,当您尝试访问两个 table 中都不存在的字段时,lua 将首先尝试访问顶级 table,后者将访问第一个 metatable 然后将在第二个 metatable.
中调用你的元方法还有另一个可能更直接的答案:使用您的 __index
元方法检查另一个 table 的命名字段:
foo = function()
print("foo")
end
f = { foo = foo }
bar = function(_, key)
if f[key] then return f[key] end
return function()
print(string.format("bar: %s", key))
end
end
mt = { __index = bar }
t = {}
setmetatable(t, mt)
t.foo() -- prints: "foo"
t.bar() -- prints: "bar: bar"
t.baz() -- prints: "bar: baz"
在 Lua 5.3.
上测试