0

我的目标是有一种标准的方式来创建具有全面多重继承的类,并且能够不仅继承到其他类,而且还能够通过new()-constructor 继承到它们自己的实例。如果我从类或其对象中调用缺失值并且该值是一个函数,我希望将其存储到类中以供以后使用,而不是在对象/实例中(大量实现相同函数时的性能问题一个类的数量)。

目前,我正在使用与官方教程系列( http://www.lua.org/pil/16.3.htmlcreateClass(...) )中提到的非常相似的 -function来创建从几乎任意数量的父类继承的类:

-- 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

它将索引元方法传递给新创建的类,该类在所有父类中搜索指定的缺失键并将其存储以供以后在调用类中使用。即使在搜索巨大的嵌套继承层次结构时,这也可以作为意图。现在,让我们介绍一个带有基本构造函数的简单类:

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

如果我们用下面的代码调用这个继承和类实现,那么我们会看到当创建类的新实例时不会调用类的-metamethod __index(比较输出的表地址),即使__index对象从其(父)类中请求缺少的值/函数,此时该类没有这样的值/函数。显然,这种描述并没有调用__index使我感到困惑的类本身的 -metamethod。我假设它总是在请求类/表的缺失值时被调用,无论来自脚本的哪个部分。

  1. 为什么在给定的示例中没有调用__index-metamethod ?MyClass
  2. 我怎样才能完成它(通过尽可能少地更改代码)?

欢迎您提出建议!

4

1 回答 1

0

我在没有完全理解的情况下找到了答案。看来,在调用类的构造函数时new,需要将类本身传递给它。这样我可以直接操作代表类的自变量。关于为什么我能够从类及其父类继承到类实例/对象而不能访问该类以进行 objetcts __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
于 2014-04-21T11:27:36.610 回答