My goal is to have a standard way of creating classes with full-scaled multiple inheritance and the ability to not only inherit to other classes but also to instances of themselves via the new()
-constructor. If I call a missing value from the class or from its object and this value is a function, I would like to have it stored into the class for later use but not in the object/instance (performance issues when implementing the same function in massive amoutns of istances of a class).
At the moment, I am using a createClass(...)
-function very similar to the one mentioned in the official tutorial series (http://www.lua.org/pil/16.3.html) to create classes that inherit from almost any number of parent classes:
-- 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
It passes an index-metamethod to the newly created class that searches all parents for the specified missing key and stores it for later use in the calling class. This works as intendet, even when searching a huge nested inheritance hierarchy. Now, let us introduce a simple class with a basic constructor:
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
If we call this inheritance and class implementations with the following code, then we see that the __index
-metamethod of the class is not invoked when a new instance of the class is created (compare the outputted table addresses), even though the __index
-metamethod of the object requests the missing value/function from its (parent-)class which does not have such a value/function at this point. Apprently, this descripancy does not invoke the __index
-metamethod of the class itself which confuses me. I would assume that it is always invoked if missing value of a class/table is requested, no matter from which part of the script.
- Why is the
__index
-metamethod of MyClass
not invoked in the given example?
- And how can I accomplish it (by making as less changes of the code as possible)?
Your suggestions are welcomed!