編集: C APIでの実装に関して特定の警告がある人の回答も参照してください。__eq
メタ__eq
メソッドは、テーブルではなくメタテーブルに属し__index
ます。
ルアで:
function my_equal(x,y)
return x.value == y.value
end
A = {} -- luaL_newmetatable(lua, "A");
A.__eq = my_equal
function new_A(value)
local a = { value = value }
return setmetatable(a, A)
end
B = {} -- luaL_newmetatable(lua, "B");
B.__eq = my_equal
function new_B(value)
local b = { value = value }
return setmetatable(b, B)
end
a = new_A()
b = new_B()
print(a == b) -- __eq is called, result is true
a.value = 5
print(a == b) -- __eq is called, result is false
あなたがしたことはこれです:
myLib_A = {}
myLib_A.__eq = my_equal
A = {} -- luaL_newmetatable(lua, "A");
A.__index = myLib_A
__eq
A のメタテーブルではなく、別の無関係なメタメソッド ( ) で使用しているまったく別のテーブルにあることに注意してください__index
。の等価演算子を解決しようとするとき、Lua はそこを調べませんa
。
Lua のマニュアルでは、これについて詳しく説明しています。
"eq": == 操作。関数 getcomphandler は、Lua が比較演算子のメタメソッドを選択する方法を定義します。メタメソッドが選択されるのは、比較される両方のオブジェクトが、選択された操作に対して同じタイプと同じメタメソッドを持っている場合のみです。
function getcomphandler (op1, op2, event)
if type(op1) ~= type(op2) then return nil end
local mm1 = metatable(op1)[event]
local mm2 = metatable(op2)[event]
if mm1 == mm2 then return mm1 else return nil end
end
「eq」イベントは次のように定義されます。
function eq_event (op1, op2)
if type(op1) ~= type(op2) then -- different types?
return false -- different objects
end
if op1 == op2 then -- primitive equal?
return true -- objects are equal
end
-- try metamethod
local h = getcomphandler(op1, op2, "__eq")
if h then
return (h(op1, op2))
else
return false
end
end
そのため、Lua が に遭遇するresult = a == b
と、次のことを行います (これは C で行われ、Lua はここでは疑似コードとして使用されます)。
-- Are the operands are the same type? In our case they are both tables:
if type(a) ~= type(b) then
return false
end
-- Are the operands the same object? This comparison is done in C code, so
-- it's not going to reinvoke the equality operator.
if a ~= b then
return false
end
-- Do the operands have the same `__eq` metamethod?
local mm1 = getmetatable(a).__eq
local mm2 = getmetatable(b).__eq
if mm1 ~= mm2 then
return false
end
-- Call the `__eq` metamethod for the left operand (same as the right, doesn't really matter)
return mm1(a,b)
ここには、メタメソッドを介して解決される resolvea.__eq
になるパスがないことがわかります。myLib_A
__index