.
経由の関数呼び出しと:
経由の関数呼び出しの違いについて混乱しています
> x = {foo = function(a,b) return a end, bar = function(a,b) return b end, }
> return x.foo(3,4)
3
> return x.bar(3,4)
4
> return x:foo(3,4)
table: 0x10a120
> return x:bar(3,4)
3
:
は何をしていますか?
コロンは、self
を最初のパラメーターとして渡すメソッドを実装するためのものです。したがって、x:bar(3,4)
はx.bar(x,3,4)
と同じでなければなりません。
定義ではexactly selfを手動で指定するのと同じです。コンパイル時に同じバイトコードを生成することさえあります。つまりfunction object:method(arg1, arg2)
はfunction object.method(self, arg1, arg2)
と同じです。
使用時に_:
_はalmost _.
_と同じです-object
および可能な副作用を確認するために特別な種類の呼び出しが内部的に使用されます計算/アクセスは一度だけ計算されます。それ以外の場合、object:method(arg1, arg2)
の呼び出しはobject.method(object, arg1, arg2)
と同じです。
正確に言うと、obj:method(1, 2, 3)
は次と同じです
_do
local _obj = obj
_obj.method(_obj, 1, 2, 3)
end
_
なぜローカル変数なのか?なぜなら、多くの人が指摘しているように、obj:method()
はobj
を取得するために__ENV
_を1回だけインデックス付けするからです。これは通常、速度を考慮するときに重要ですが、この状況を考慮してください。
_local tab do
local obj_local = { method = function(self, n) print n end }
tab = setmetatable({}, {__index = function(idx)
print "Accessing "..idx
if idx=="obj" then return obj_local end
end})
end
tab.obj.method(tab.obj, 20)
--> Accessing obj
--> Accessing obj
--> 20
tab.obj:method(10)
--> Accessing obj
--> 10
_
ここで、___index
_メタメソッドが単に何かを印刷する以上のことをしたと想像してください。カウンターを増やしたり、ファイルに何かを記録したり、データベースからランダムなユーザーを削除したりすると想像してください。それを2回または1回だけ行うことには大きな違いがあります。この場合、obj.method(obj, etc)
とobj:method(etc)
には明確な違いがあります。