What to use as metatable?

Viewed 55

Reading http://lua-users.org/wiki/LuaClassesWithMetatable the Vector example uses the following technique for the metatable:

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

Supposing we want to use __add to support the + operator, we need to explicitly mention it in the metatable, and also we need to reorder things, so that the metatable and the constructor are mentioned after 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

To avoiding having to mention each metamethod in the metatable, I can set Vector itself as the metatable, then I can add __add (plus, obviously, __index) as a method of 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

is the latter not recommended and why?

1 Answers

and also we need to reorder things, so that the metatable and the constructor are mentioned after Vector:add

No. A table is a reference. On adding metatable, it is not deep copied. You can add fields to it later, and it will affect the metatable.

This is over-complicated:

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

Simply do this:

Vector.__index = Vector

See https://codereview.stackexchange.com/a/253022/230923 for an example of a Lua "class".

Related