如果子类的对象调用__index,则将继承的表成员存储到子类中

时间:2014-04-21 09:59:12

标签: inheritance lua meta-method

我的目标是使用标准方法创建具有完全多重继承的类,并且不仅可以通过new()构造函数继承其他类,还可以继承自己的实例。如果我从类或其对象中调用缺少的值并且此值是一个函数,我希望将它存储到类中供以后使用,但不能存储在对象/实例中(在大量实现相同功能时的性能问题)一个班级的节制。)

目前,我使用的createClass(...)函数非常类似于官方教程系列(http://www.lua.org/pil/16.3.html)中提到的函数,用于创建从几乎任意数量的父类继承的类: / p>

-- 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 - 元方法(比较输出的表地址) ,即使对象的__index - 元方法从其(父 - )类请求缺少的值/函数,此类此时没有这样的值/函数。显然,这个描述并没有调用类本身的__index - 元方法,这让我感到困惑。如果请求缺少类/表的值,我会假设它始终被调用,无论脚本的哪个部分。

  1. 为什么__index - MyClass的元方法未在给定示例中调用?
  2. 我怎样才能完成它(尽量减少对代码的更改)?
  3. 欢迎您的建议!

1 个答案:

答案 0 :(得分:0)

我没有完全理解答案就找到了答案。看来,在调用类new的构造函数时,需要将类本身传递给它。这样我就可以直接操作代表类的自变量。仍然存在混淆,为什么我能够从类及其父类继承到类实例/对象,而无法在对象__index - metamethod中访问任何其他操作的类。

这个类定义最终完成了这项工作:

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