web-dev-qa-db-fra.com

Différence entre . et: à Lua

Je suis confus quant à la différence entre les appels de fonction via . et via :

> 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

Quel est le : Faire ?

156
Jason S

Le deux-points sert à implémenter des méthodes qui passent self comme premier paramètre. Donc x:bar(3,4) devrait être identique à x.bar(x,3,4).

214
BMitch

Pour la définition, c'est exactement la même chose que de spécifier soi-même manuellement - cela produira même le même bytecode lors de la compilation. C'est à dire. function object:method(arg1, arg2) est identique à function object.method(self, arg1, arg2).

Lors de l'utilisation, : Est presque identique à . - un type spécial d'appel sera utilisé en interne pour s'assurer que object et tout côté possible- les effets des calculs/accès ne sont calculés qu'une seule fois. L'appel de object:method(arg1, arg2) est par ailleurs identique à object.method(object, arg1, arg2).

25
Oleg V. Volkov

Pour être complètement précis, obj:method(1, 2, 3) est identique à

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

Pourquoi la variable locale? Parce que, comme beaucoup l'ont souligné, obj:method() indexe _ENV Une seule fois pour obtenir obj. Cela est normalement important pour la vitesse, mais considérez cette situation:

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

Imaginez maintenant que la métaméthode __index Fasse plus que simplement imprimer quelque chose. Imaginez qu'il augmente un compteur, enregistre quelque chose dans un fichier ou supprime un utilisateur aléatoire de votre base de données. Il y a une grande différence entre le faire deux fois ou une seule fois. Dans ce cas, il y a une nette différence entre obj.method(obj, etc) et obj:method(etc).

17
DarkWiiPlayer