我需要关于Metatable.__index的澄清。

我之前问过为什么我的元方法没有被Lua所寻找,然后被告知可以通过将__index设置为我的元表来解决问题,因此我认为调用方法时在元表中通过索引查找,但是现在我需要在元表上使用索引括号[],所以__index被分配为从其中一个表中返回索引,我该如何解决同时使用方法和索引括号的功能需求

我编写了一个最小示例,说明了问题:

TestMetatable = {DataTable = {}}
TestMetatable.__index = TestMetatable

function TestMetatable.new()
    local Tmp = {}
    setmetatable(Tmp,TestMetatable)

    Tmp.DataTable = {1}

    return Tmp
end

function TestMetatable:TestMethod()
    print("Ran Successfully")
end

function TestMetatable.__index(self,index)
    return self.DataTable[index]
end

local Test = TestMetatable.new()

-- 需要同时使用两种功能
print(Test[1])
Test:TestMethod()
点赞
用户734069
用户734069

你需要理解 __index__newindex 之间的区别,以及它们与主表当前内容的关系。

只有以下条件都成立时,才会调用/访问 __newindex

  • 通过 tbl[index] = expr(或类似语法,如 tbl.name = expr )将一个值设置到主表中。
  • 当你尝试设置到主表中的键 在主表中不存在

后者经常会使人们犯错。这是你在这里遇到问题的原因,因为 __index 仅在以下情况下才被访问:

  • 当从主表中读取的键 在主表中不存在

因此,如果你想过滤对表的 每个 读取和写入,那么该表 _必须始终为空_。因此,这些读取和写入需要进入为每个新对象创建的 其他 表中。因此,你的 new 函数需要创建两个表:一个保持为空,另一个包含所有数据。

说实话,我希望 Lua 有一种方法来创建一个仅为空的 userdata 片段,你可以将用户定义的元表绑定到它,以避免这些问题。

2013-08-02 21:48:01
用户1301806
用户1301806

以下是我的解决方案,根据 Nicol Bolas 的解决方案,如果能够解决其他人的困惑,那就更好了 :-)

TestMetatable = {DataTable = {}, FunctionTable = {}}

function TestMetatable.new()
    local Tmp = {}
    setmetatable(Tmp,TestMetatable)

    Tmp.DataTable = {1}
    Tmp.FunctionTable = TestMetatable

    return Tmp
end

function TestMetatable:TestMethod()
    print("成功运行")
end

function TestMetatable.__index(self,index)
    if type(index) == "string" then
        return self.FunctionTable[index]
    else
        return self.DataTable[index]
    end
end

local Test = TestMetatable.new()

-- 需要这两种功能
print(Test[1])
Test:TestMethod()
2013-08-02 22:54:34