Unterschied zwischen . und: in Lua

Ich bin verwirrt über den Unterschied zwischen functionsaufrufen via . und über :

 > 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 

Was ist das?

   

    Der Doppelpunkt dient zum Implementieren von Methoden, die self als ersten Parameter übergeben. Also sollte x:bar(3,4) dasselbe wie x.bar(x,3,4) .

    Für die Definition ist es genau das selbe wie self manually – es wird sogar den gleichen Bytecode beim Kompilieren erzeugen. Ie function object:method(arg1, arg2) ist das gleiche wie die function object.method(self, arg1, arg2) .

    Beim Gebrauch : ist fast das Gleiche wie . – Eine spezielle Art von Aufruf wird intern verwendet, um sicherzustellen, dass object und mögliche Nebenwirkungen von Berechnungen / Zugriff nur einmal berechnet werden. Aufrufendes object:method(arg1, arg2) ist ansonsten dasselbe wie object.method(object, arg1, arg2) .

    Um vollkommen präzise zu sein, ist obj:method(1, 2, 3) dasselbe wie

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

    Warum die lokale Variable? Wie bereits erwähnt, obj:method() nur einmal _ENV , um obj zu erhalten. Dies ist normalerweise wichtig, wenn man die Geschwindigkeit berücksichtigt, aber bedenken Sie diese 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 

    __index Sie sich nun vor, dass das __index metamethod mehr getan hat als nur etwas zu drucken. Stellen Sie sich vor, Sie hätten einen Zähler erhöht, etwas in einer Datei protokolliert oder einen zufälligen Benutzer aus Ihrer database gelöscht. Es ist ein großer Unterschied, ob man das zweimal oder nur einmal macht. In diesem Fall gibt es einen klaren Unterschied zwischen obj.method(obj, etc) und obj:method(etc) .