Arasındaki fark. ve: Lua'da


174

Üzerinden .ve üzerinden işlev çağrıları arasındaki fark hakkında kafam karıştı:

> 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

Ne :yapıyor?


Yanıtlar:


237

İki nokta üst üste selfilk parametre olarak geçen yöntemleri uygulamak içindir . Yani x:bar(3,4)aynı olmalı x.bar(x,3,4).


55
ah ... yani nesne yönelimli sözdizimsel şeker.
Jason S

7
Kesinlikle. Tüm referans kılavuzunda, bu konuda verdikleri tek bulanıklık "İki nokta sözdizimi, yöntemleri, yani, fazladan bir ekstra parametre özü olan işlevleri tanımlamak için kullanılır." (5.0 kılavuzu, pdf sayfasının altı 19)
BMitch

2
ooh ahh ... Resmi belgelerin bunun neresinde olduğunu soracaktım, ama sen beni dövüyordun. güzel yapılmış. :-)
Jason S

1
@keyle selfNesnenin ilk parametre olarak gideceğine ve özellik değerine bağlıdır.
Hydroper

8
Sanal makine yalnızca bir kez aldığından, aradığınız nesne yerel değilse @key Colon sözdizimi biraz daha hızlı olur. Temelde gibi sözdizimi dot object.method(object,args)Geri alma işlemlerinde objectiki kez, süre object:method(arg)Geri alma işlemlerinde objectsadece bir kez. Genel object, değer veya tablo alanı ise, bundan :daha hızlıdır .. .asla daha hızlı değildir :.
negamartin

28

Tanım olarak , kendini manuel olarak belirtmekle tamamen aynıdır - derlemede aynı bayt kodunu bile üretecektir. Yani function object:method(arg1, arg2)ile aynı function object.method(object, arg1, arg2).

Kullanımda :olduğu hemen hemen aynı .çağrının özel bir tür emin olmak için dahili olarak kullanılacaktır - objectve hesaplamalar / erişimin olası yan etkiler sadece bir kez hesaplanır. Arama object:method(arg1, arg2), aksi takdirde ile aynıdır object.method(object, arg1, arg2).


21

Tamamen hassas olması için, obj:method(1, 2, 3)aynı

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

Neden yerel değişken? Çünkü, birçok kişinin belirttiği gibi, obj:method()sadece bir _ENVkez indeksler obj. Bu normalde hızı dikkate alırken önemlidir, ancak bu durumu göz önünde bulundurun:

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

Şimdi __indexmetamethod'un bir şey yazdırmaktan daha fazlasını yaptığını düşünün . Bir sayacı artırdığını, bir dosyaya bir şey kaydettiğini veya rastgele bir kullanıcıyı veritabanınızdan sildiğini düşünün. Bunu iki kez veya sadece bir kez yapmak arasında büyük bir fark var. Bu durumda obj.method(obj, etc)ve arasında açık bir fark vardır obj:method(etc).


Gerçekten böyle şeyler için endişelenmemelisin. Gerekirse , mimarinizle ilgili çok yanlış bir şey var .
val diyor Reinstate Monica

2
Bunun tam tersi olduğunu söyleyebilirim; iyi kod, ilişkisiz kodun uygulama ayrıntıları hakkında herhangi bir varsayımda bulunmamalıdır. İşlev çağrıları hafızaya alınabilir veya hafızaya alınmayabilir, bu da onları gerektiğinden daha sık çağırmanın iyi bir uygulama olduğu anlamına gelmez.
DarkWiiPlayer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.