需要帮助理解将表的元方法设置为该表

我不确定将 Stack 的元方法设置为 Stack 的意义何在。

我搜索了一下,但是没有一个解释十分清楚。我知道有时实例可能需要回退到 Stack 以获取任何缺失的方法,但希望有一个更清晰的解释。

Stack = {}
Stack.__index = Stack
点赞
用户2616735
用户2616735

假设你有一个“2D向量”“类”,它有一个.x和一个.y。你为它们编写了一个dotproduct函数:

function dotproduct(a, b)
    return a.x * b.x + a.y * b.y
end

让你可以编写foo:dot(bar)的最简单方法是在每个新实例上放置一个.dot属性:

-- Make a "V2" namespace
local V2 = {}
function V2.new(x, y)
    return {
        x = x,
        y = y,

        -- Attach any methods to the object, also
        dot = dotproduct,
    }
end

然而,随着方法的增多,对于两个原因来说这变得更糟糕。一个是你的对象变得更大了——尽管你只需要在每个向量上拥有两个数字,但大部分哈希表是始终相同的函数!另一个是多个构造函数变得困难,因为你需要在每个构造函数中复制相同的工作。

解决这个问题的方法是使用__index元表。不是将每个方法复制到每个新对象上,而是仅在需要“丢失”方法时指向其位置:

V2.dot = dotproduct
function V2.new(x, y)
    return setmetatable({x = x, y = y}, {__index = V2})
end

这种设计有一个小缺点。首先,除了每个表之外,你还分配了一个新的元表,这是一种浪费内存的做法(所有的元表都是相同的)。其次,你没有机会覆盖其他方法,而不会增加这个新元表(同样是以前的烦恼)。

因此,我们将V2作为唯一的元表:

V2.__index = V2
function V2.new(x, y)
   return setmetatable({x = x, y = y}, V2)
end
2019-01-13 01:16:07