如何使用元表?

阅读 http://lua-users.org/wiki/LuaClassesWithMetatable 后,向量例子使用了以下元表技巧:

Vector={}
Vector_mt={__index=Vector}

function Vector:new(x,y)
    return setmetatable({x=x,y=y},Vector_mt)
end

function Vector:add(v)
    return Vector:new(self.x+v.x,self.y+v.y)
end

假设我们想要使用 __add 来支持 + 运算符,我们需要在元表中明确提到它,同时我们需要重新排列元素,以便将元表和构造函数放在 Vector:add 之后:

Vector={}

function Vector:add(v)
    return Vector:new(self.x+v.x,self.y+v.y)
end

Vector_mt={__index=Vector,__add=Vector.add}

function Vector:new(x,y)
    return setmetatable({x=x,y=y},Vector_mt)
end

为了避免在元表中提到每个元方法,我可以将 Vector 本身设置为元表,然后我可以将 __add(加号,显然,__index)作为 Vector 的方法添加:

Vector={}

function Vector:new(x,y)
    return setmetatable({x=x,y=y},Vector)
end

function Vector:add(v)
    return Vector:new(self.x+v.x,self.y+v.y)
end

function Vector:__index(k)
    return Vector[k]
end

function Vector:__add(b)
    return self:add(b)
end

后一种方式不推荐使用,原因是什么?

点赞
用户6632736
用户6632736

我们还需要重新排序一下,把 metatable 和构造函数放在 Vector:add 后面提到。

不,一个表是一个引用。在加入 metatable 时,它不会被深层复制。您稍后可以向其中添加字段,并且这将影响 metatable。

这个过于复杂了:

function Vector:__index(k)
    return Vector[k]
end

可以直接这么做:

Vector.__index = Vector

请参见 https://codereview.stackexchange.com/a/253022/230923,了解 Lua "class" 的示例。

2020-12-11 03:35:10