我需要澄清Metatable .__ index

时间:2013-08-02 21:05:56

标签: lua metatable

我之前问过为什么我的方法不是由Lua找到我的方法,并且被告知通过将__index设置为我的metatable,它会解决问题,所以我假设一个方法被调用是在metatable中通过索引进行搜索,但我现在遇到了一个问题,我需要在myatable上使用索引括号[],因此__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()

-- both functionalities are needed
print(Test[1])
Test:TestMethod()

2 个答案:

答案 0 :(得分:6)

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

仅当满足以下所有条件时,才会调用/访问

__newindex

  • 当您在主表格中设置值时,请tbl[index] = expr(或等效语法,如tbl.name = expr)。
  • 当您尝试在主表中设置的密钥在主表中不存在时

第二个经常绊倒人。这就是你的问题,因为__index仅在 访问

时:

  • 当主表格中正在从主表中读取的密钥

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

老实说,我希望Lua有办法创建一个空的userdata,你可以将用户定义的metatable绑定到,只是为了避免这些问题。

答案 1 :(得分:0)

根据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("Ran Successfully")
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()

-- both functionalities are needed
print(Test[1])
Test:TestMethod()