我有一个情况,其中两个库L、M都试图为_G(分别命名为mL、mM)设置元表。元表中唯一的内容是__index。
我如何链接这两个元表,以便如果一个__index失败,则调用另一个__index呢?
我有一个情况,其中两个库L、M都试图为_G(分别命名为mL、mM)设置元表。元表中唯一的内容是__index。
我如何链接这两个元表,以便如果一个__index失败,则调用另一个__index呢?
mL
和 mM
,如果返回 nil
,则检查另一个元表。local metatbl = {}
metatbl.tbls = {mL, mM};
function metatbl.__index(intbl, key)
for i, mtbl in ipairs(metatbl.tbls) do
local mmethod = mtbl.__index
if(type(mmethod) == "function") then
local ret = mmethod(table, key)
if ret then return ret end
else
if mmethod[key] then return mmethod[key] end
end
return nil
end
end
setmetatable(_G,metatbl)
_G
的元表本身来修复L和M所造成的问题,那么您只需要插入自己的元表即可进行组合搜索,例如:combined_metatable = {
__index = function (t, k)
return mL.__index (t, k) or mM.__index (t, k)
end
}
setmetatable (_G, combined_metatable)
这样做的好处是不必直接操作 mL
或 mM
。
如果您没有事后更正的机会,可以修改库元表的 __index
条目以进行组合搜索:
local original_mM_index = mM.__index
local original_mL_index = mL.__index
local function L_then_M_index (t, k)
return original_mL_index (t, k) or original_mM_index (t, k)
end
mL.__index = L_then_M_index
mM.__index = L_then_M_index
[请注意,由于两个库元表都被修改,因此无论哪个安装在最后(“赢得”比赛),这都会起作用。]
getmetatable(getfenv()).__metatable = function ( o ) return { } end
或者
local orig_setmetatable = setmetatable
function setmetatable ( ob , mt )
if ob == getfenv() or ob == _G then
return ob
else
return orig_setmetatable(ob,mt)
end
end
local env_indexes = {}
setmetatable(_G,{__index=function(t,k) for i,m in ipairs(env_indexes) do local v=m[k]; if v then return v end end return nil end } )
local orig_setmetatable = setmetatable
function setmetatable ( ob , mt )
if ob == _G then
table.insert ( env_indexes , mt.__index )
return ob
else
return orig_setmetatable(ob,mt)
end
end