尝试使用元表创建lua代理

尝试使用元表创建lua代理,lua,hook,metatable,Lua,Hook,Metatable,我读过关于元表(和)的书,我问自己是否可以创建一个函数调用代理,只需在\uu index表中添加一个同名函数,这样它就可以调用索引函数(我的),然后我就可以调用普通函数了 这就是我尝试过的: local test = {} test.static = function () print("static") end -- The normal function local old = getmetatable(test) or {} -- Get the orginal meta old.__i

我读过关于元表(和)的书,我问自己是否可以创建一个函数调用代理,只需在
\uu 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 )
请尝试给出a read,特别是
\u index
方法的描述,其内容如下:

  • \uu index:索引访问
    表[键]
    。当表不是表或表中不存在键时,会发生此事件。元方法在表中查找

    不管名称如何,此事件的元方法可以是函数或表。如果它是一个函数,则使用table和key作为参数调用它,调用的结果(调整为一个值)就是操作的结果。如果它是一个表,则最终结果是使用键对此表进行索引的结果。(此索引是常规的,不是原始的,因此可以触发另一个元方法。)

我们可以看出你的想法是倒退的。只有在原始表不包含键的情况下,才会查找由
\u 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!'