web-dev-qa-db-ja.com

との差 。および:Luaで

.経由の関数呼び出しと:経由の関数呼び出しの違いについて混乱しています

> 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

:は何をしていますか?

156
Jason S

コロンは、selfを最初のパラメーターとして渡すメソッドを実装するためのものです。したがって、x:bar(3,4)x.bar(x,3,4)と同じでなければなりません。

214
BMitch

定義ではexactly selfを手​​動で指定するのと同じです。コンパイル時に同じバイトコードを生成することさえあります。つまりfunction object:method(arg1, arg2)function object.method(self, arg1, arg2)と同じです。

使用時に_:_はalmost _._と同じです-objectおよび可能な副作用を確認するために特別な種類の呼び出しが内部的に使用されます計算/アクセスは一度だけ計算されます。それ以外の場合、object:method(arg1, arg2)の呼び出しはobject.method(object, arg1, arg2)と同じです。

25
Oleg V. Volkov

正確に言うと、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)には明確な違いがあります。

17
DarkWiiPlayer