Разница между ними. и: в Луа
Я запутался в разнице между вызовами функций через .
и через :
> 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 ответа:
двоеточие предназначено для реализации методов, которые проходят
self
в качестве первого параметра. Так чтоx:bar(3,4)
должно быть то же самое, что иx.bar(x,3,4)
.
по определению ровно то же самое, что указать self вручную - он даже будет производить тот же байт-код при компиляции. То есть
function object:method(arg1, arg2)
такой же, какfunction object.method(self, arg1, arg2)
.использовать
:
и почти то же самое, что.
- специальный вид вызова будет использоваться внутри, чтобы убедиться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()
только индексы_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)
.