2011-11-13 3 views
4

두 라이브러리 L, M이 _G (각각 mL, mM으로 명명 됨)에 대한 메타 테이블을 설정하려고하는 상황이 있습니다. 메타 테이블의 유일한 것은 __index입니다.Chain Lua 메타 테이블

하나의 __index가 실패하면 다른 인덱스에서 인덱스를 호출하도록이 두 메타 테이블을 어떻게 연결할 수 있습니까?

답변

2

모두 mLmM를 저장 한 메타 테이블을 가지고, 하나는 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) 
+0

-1의 이유는 무엇입니까? –

1

는 라이브러리 후, 코드가 _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 

가 [주를 그 모두로 라이브러리 메타 테이블이 수정 된 경우 마지막 설치 (경쟁에서 "우승"한 것)에 따라 작동합니다.]

1

__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 

을 그렇지 않으면이 라이브러리는 일을해야 할 아주 나쁜 관행입니다; 저자에게하지 말라고!

관련 문제