5

我之前问过为什么 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()

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

2 回答 2

8

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

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

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

第二个经常绊倒人们。这就是您的问题,因为__index在以下情况下访问:

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

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

老实说,我希望 Lua 有一种方法来创建一个空的用户数据,您可以将一个用户定义的元表绑定到它,以避免这些问题。

于 2013-08-02T21:48:01.297 回答
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()
于 2013-08-02T22:54:34.430 回答