私の目標は、本格的な多重継承を備えたクラスを作成する標準的な方法と、他のクラスへの継承だけでなく、new()
コンストラクターを介したそれら自身のインスタンスへの継承も可能にすることです。クラスまたはそのオブジェクトから欠損値を呼び出し、この値が関数である場合、オブジェクト/インスタンスではなく、後で使用するためにクラスに格納したいと考えています (同じ関数を大量に実装する場合のパフォーマンスの問題)クラスのインスタンスの量)。
現時点では、公式のチュートリアル シリーズ ( http://www.lua.org/pil/16.3.htmlcreateClass(...)
)で言及されている関数と非常によく似た関数を使用して、ほぼ任意の数の親クラスから継承するクラスを作成しています。 :
-- 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 を渡します。このメソッドは、指定された欠落しているキーをすべての親で検索し、後で呼び出し元のクラスで使用できるように格納します。これは、ネストされた巨大な継承階層を検索する場合でも、目的として機能します。それでは、基本的なコンストラクターを持つ単純なクラスを紹介しましょう。
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
。オブジェクトは、この時点でそのような値/関数を持たない (親) クラスから欠落している値/関数を要求します。__index
どうやら、この記述は、私を混乱させるクラス自体の -metamethod を呼び出しません。スクリプトのどの部分からでも、クラス/テーブルの欠損値が要求された場合は常に呼び出されると想定します。
__index
与えられた例で-metamethod がMyClass
呼び出されないのはなぜですか?- そして、どうすればそれを達成できますか (コードの変更をできるだけ少なくすることによって)?
あなたの提案は大歓迎です!