尝试使用元表创建 lua 代理
Trying to make a lua proxy with metatables
我读过有关 metatables (here and here) 的信息,我问自己是否可以通过向 [=12 添加一个同名函数来创建一个函数调用代理=] table, 让它调用索引函数(我的),然后我就可以正常调用了。
这是我试过的:
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 )
尝试给出 official source a read, specifically §2.4 – Metatables and Metamethods
和 __index
方法的描述,内容为:
__index: The indexing access table[key]
. This event happens when table is not a table or when key is not present in table. The metamethod is looked up in table.
Despite the name, the metamethod for this event can be either a function or a table. If it is a function, it is called with table and key as arguments, and the result of the call (adjusted to one value) is the result of the operation. If it is a table, the final result is the result of indexing this table with key. (This indexing is regular, not raw, and therefore can trigger another metamethod.)
可见你的思维是倒退的。 __index
元方法引用的 table 上的属性仅在原始 table 不包含键时才会被查找。
如果您想 'hook' 一个函数,您需要覆盖它,可能会保存原始函数以便稍后恢复它。如果你想在功能上附加到现有函数,你可以编写一个简洁的小挂钩函数,它只是在函数周围创建一个闭包,依次调用它们。
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!'
或者,您可以在元 table 之间切换,假设原始 table 永远不会覆盖感兴趣的键,以获得不同的结果:
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!'
我读过有关 metatables (here and here) 的信息,我问自己是否可以通过向 [=12 添加一个同名函数来创建一个函数调用代理=] table, 让它调用索引函数(我的),然后我就可以正常调用了。
这是我试过的:
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 )
尝试给出 official source a read, specifically §2.4 – Metatables and Metamethods
和 __index
方法的描述,内容为:
__index: The indexing access
table[key]
. This event happens when table is not a table or when key is not present in table. The metamethod is looked up in table.Despite the name, the metamethod for this event can be either a function or a table. If it is a function, it is called with table and key as arguments, and the result of the call (adjusted to one value) is the result of the operation. If it is a table, the final result is the result of indexing this table with key. (This indexing is regular, not raw, and therefore can trigger another metamethod.)
可见你的思维是倒退的。 __index
元方法引用的 table 上的属性仅在原始 table 不包含键时才会被查找。
如果您想 'hook' 一个函数,您需要覆盖它,可能会保存原始函数以便稍后恢复它。如果你想在功能上附加到现有函数,你可以编写一个简洁的小挂钩函数,它只是在函数周围创建一个闭包,依次调用它们。
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!'
或者,您可以在元 table 之间切换,假设原始 table 永远不会覆盖感兴趣的键,以获得不同的结果:
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!'