我已经阅读了有关元数据(here和here)的内容,我问自己是否可以通过向__index
添加具有相同名称的函数来创建函数调用代理表,以便它调用索引函数(我的),然后我可以调用正常函数。
这是我尝试过的:
local test = {}
test.static = function () print("static") end -- The normal function
local old = getmetatable(test) or {} -- Get the orginal meta
old.__index = {
static = function () print("hook") end -- Adding my function
}
test.static() -- call just for test ( prints -> static )
test = setmetatable( test , old ) -- setting the metatable
test.static() -- call just for test ( prints -> static, but should be hook )
答案 0 :(得分:0)
尝试给official source一个读物,特别是§2.4 – Metatables and Metamethods
,以及__index
甲基方法的描述,内容如下:
__ index :索引访问
table[key]
。当表不是表或表中没有键时,会发生此事件。 metame方法在表格中查找。尽管名称,此事件的元方法可以是函数或表。如果它是一个函数,则使用table和key作为参数调用它,并且调用的结果(调整为一个值)是操作的结果。如果是表,则最终结果是使用键索引此表的结果。 (这种索引是常规的,而不是原始索引,因此可以触发另一种元方法。)
我们可以看到你的想法是倒退的。仅当原始表不包含密钥时,才会查找__index
元方法引用的表上的属性。
如果你想“挂钩”一个功能,你需要覆盖它,可能会保存原件以便以后恢复它。如果你想在函数上使用现有函数,你可以编写一个简洁的小挂钩函数,它只是在函数周围创建一个闭包,依次调用它们。
local function hook (original_fn, new_fn)
return function (...)
original_fn(...)
new_fn(...)
end
end
local test = {}
test.foo = function () print('hello') end
test.foo = hook(test.foo, function () print('world!') end)
test.foo() --> prints 'hello' then 'world!'
或者,您可以在元表之间切换,假设原始表永远不会覆盖感兴趣的键,以获得不同的结果:
local my_table, default, extra = {}, {}, {}
function default.foo () print('hello') end
function extra.foo() print('world!') end
local function set_mt (t, mt)
mt.__index = mt
return setmetatable(t, mt)
end
set_mt(my_table, default)
my_table.foo() --> prints 'hello'
set_mt(my_table, extra)
my_table.foo() --> prints 'world!'