두 라이브러리 L, M이 _G (각각 mL, mM으로 명명 됨)에 대한 메타 테이블을 설정하려고하는 상황이 있습니다. 메타 테이블의 유일한 것은 __index입니다.Chain Lua 메타 테이블
하나의 __index가 실패하면 다른 인덱스에서 인덱스를 호출하도록이 두 메타 테이블을 어떻게 연결할 수 있습니까?
두 라이브러리 L, M이 _G (각각 mL, mM으로 명명 됨)에 대한 메타 테이블을 설정하려고하는 상황이 있습니다. 메타 테이블의 유일한 것은 __index입니다.Chain Lua 메타 테이블
하나의 __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
가 [주를 그 모두로 라이브러리 메타 테이블이 수정 된 경우 마지막 설치 (경쟁에서 "우승"한 것)에 따라 작동합니다.]
__metatable을 사용하여 실제로 메타 테이블이 아니거나 라이브러리에 다른 설정 가능 테이블을 제공합니다. _G 메타 테이블을 변경할 수 없습니다.
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
는
당신은 여전히 메타 테이블에 수행하는 일들을 추적하려면 (라이브러리가 일을하는 방법에 따라); 반환 산부인과 전에 MT 통해보고 (당신이 실제로 체인 __index 조회를 원하는 경우, 테이블에 추가) :
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
을 그렇지 않으면이 라이브러리는 일을해야 할 아주 나쁜 관행입니다; 저자에게하지 말라고!
-1의 이유는 무엇입니까? –