Разница между . и: в Lua - PullRequest
       30

Разница между . и: в Lua

152 голосов
/ 06 февраля 2011

Меня смущает разница между вызовами функций через . и через :

> 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

Что делает :?

Ответы [ 3 ]

207 голосов
/ 06 февраля 2011

Двоеточие предназначено для реализации методов, которые передают self в качестве первого параметра.Так что x:bar(3,4) должно совпадать с x.bar(x,3,4).

25 голосов
/ 04 октября 2013

Для определения это точно , то же самое, что и указание себя вручную - он даже будет генерировать тот же байт-код при компиляции. То есть function object:method(arg1, arg2) совпадает с function object.method(self, arg1, arg2).

При использовании : равен почти так же, как . - для внутреннего вызова будет использоваться специальный тип вызова, чтобы убедиться, что object и любые возможные побочные эффекты вычислений / доступа рассчитаны только однажды. Вызов object:method(arg1, arg2) в остальном совпадает с object.method(object, arg1, arg2).

16 голосов
/ 17 августа 2018

Если быть точным, obj:method(1, 2, 3) совпадает с

do
  local _obj = obj
  _obj.method(_obj, 1, 2, 3)
end

Почему локальная переменная? Потому что, как отмечали многие, obj:method() только один раз индексирует _ENV, чтобы получить obj. Обычно это просто важно при рассмотрении скорости, но рассмотрим следующую ситуацию:

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 сделал больше, чем просто напечатал что-то. Представьте, что он увеличил счетчик, записал что-то в файл или удалил случайного пользователя из вашей базы данных. Есть большая разница между этим дважды или только один раз. В этом случае существует четкая разница между obj.method(obj, etc) и obj:method(etc).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...