2014-04-21 5 views
0

저의 목표는 풀 스케일 된 다중 상속을 가진 클래스를 생성하는 표준 방법과 다른 클래스뿐만 아니라 인스턴스로 상속 할 수있는 능력을 갖는 것입니다 new()- 생성자를 통해 클래스 또는 해당 개체에서 누락 된 값을 호출하고이 값이 함수 인 경우 나중에 사용하기 위해 클래스에 저장하지만 개체/인스턴스에는 저장하지 않도록하고 싶습니다 (대규모 함수에서 동일한 함수를 구현할 때의 성능 문제 수업의 상상력의 amoutns). 순간 __index가 자식 클래스의 객체에 의해 호출되는 경우 상속 된 테이블 멤버를 자식 클래스로 저장

, 내가 사용하고 부모 클래스의 거의 모든 수의 상속 클래스를 생성하는 공식 튜토리얼 시리즈 ( http://www.lua.org/pil/16.3.html)에 언급 된 것과 매우 유사 createClass(...) α- 함수 :

-- look up for k in list of tables plist 
local function search (k, plist) 
    for i=1, #plist do 
     local v = plist[i][k]  -- try i-th superclass 
     if v then return v end 
    end 
end 

local function createClass (...) 
    local args = {...}; 
    local c = {}; 
    -- search all provided parent classes for variables/functions to inherit and include them 
    -- could be done without including them (deeply nested inheritance might be an issue this way 
    -- due to repeated search calls for each use of an inherited function) 
    setmetatable(c, {__index = function (t, k) 
     local v = search(k, args); 
     t[k] = v; 
     print(t, " ...looking for... ", k, v); 
     return v; 
    end}) 
    return c; 
end 

그것을 index-metamethod를 새로 생성 된 클래스에 전달하여 모든 부모가 지정된 누락 된 키를 검색하고 나중에 호출 클래스에서 사용할 수 있도록 저장합니다. 거대한 중첩 된 상속 계층 구조를 검색 할 때도 intendet으로 작동합니다. 이제, 우리는 기본 생성자와 간단한 클래스를 소개하자 : 우리는 다음과 같은 코드로이 상속과 클래스 구현을 호출하는 경우

local P = {}; 
local MyClass = P; 

function P.new() 
    local self = {}; 
    local priv = {}; 
    setmetatable(self, {__index = function (t, k) 
     -- shouldn't this invoke __index-metamethod of P because P does not already have k 
     -- at this stage of the program? 
     local v = P[k]; 
     print(t, " ...looking for ... ", k, v); 
     if(type(v) == "function") then 
      -- ??? maybe do somethine else here to enforce __index of class P 
     else 
      t[k] = v; 
     end 
     return v; 
    end}); 

    self.testSelf = function() print("testSelf") end; 
    priv.testPriv = "testPriv!"; 

    function self.accessPriv() 
     return priv; 
    end 

    return self; 
end 

function P.TEST() 
    print("calling TEST"); 
end 

는, 우리는 클래스의 __index -metamethod가 호출되지 않은 것을 볼 때 새를 개체의 __index - 메타 메서드가이 값/함수가없는 (부모) 클래스에서 누락 된 값/함수를 요청하더라도 클래스의 인스턴스가 만들어집니다 (출력 된 테이블 주소 비교). 어쨌든,이 descripancy는 나를 혼란스럽게하는 클래스 그 자체의 메타 메서드를 호출하지 않습니다. 클래스/테이블의 누락 된 값이 요청 된 경우 스크립트의 어느 부분이든 상관없이 항상 호출된다고 가정합니다.

  1. 왜 주어진 예제에서 호출되지 MyClass__index -metamethod입니까?
  2. 가능한 한 코드를 변경하지 않고 어떻게 구현할 수 있습니까?

귀하의 제안을 환영합니다!

+0

추가를 (주어진 예제에 대해 테스트). –

답변

0

완전히 이해하지 못한 채 대답을 찾았습니다. 클래스 new의 생성자를 호출 할 때 클래스 자체를 전달해야합니다. 이렇게하면 클래스를 나타내는 자체 변수를 직접 조작 할 수 있습니다. 클래스와 그 부모를 클래스 인스턴스/객체로 상속 할 수있는 이유는 여전히 혼란스럽지 만 객체 클래스에서는 다른 작업의 클래스에 액세스 할 수 없습니다. __index -metamethod.

이 클래스 정의는 마지막으로 작업 수행이 그것을 확실히 클래스와 슈퍼 클래스를 위해 작동하는 방법이기 때문에 나는 그것의 클래스 객체 __index` - 메타 메서드`의 체인에 대한 내 가정을 위해 만든 :

local P = {}; 
local MyClass = P; 

-- must pass class itself while creating new object of it (don't know why...) 
function P:new() 
    local pub = {}; 
    local priv = {}; 
    setmetatable(pub, {__index = function (t, k) 
     local v = P[k]; 
     -- store functions into the class for later use (less duplicates) 
     -- and all other inherited variables into the objects itself 
     if (type(v) == "function") 
      self[k] = v; 
     else 
      t[k] = v; 
     end 
     return v; 
    end}); 

    pub.testSelf = function() print("testSelf") end; 
    priv.testPriv = "testPriv!"; 

    function pub.accessPriv() 
     return priv; 
    end 

    return pub; 
end 

function P.TEST() 
    print("calling TEST"); 
end