ความแตกต่างระหว่าง . และ: ใน Lua


174

ฉันสับสนเกี่ยวกับความแตกต่างระหว่างฟังก์ชั่นการโทรผ่าน.และผ่าน:

> 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

กำลัง:ทำอะไรอยู่?


1
ที่เกี่ยวข้อง: stackoverflow.com/questions/3779671/…
finnw

คำตอบ:


237

โคลอนใช้สำหรับการนำวิธีการที่ผ่านselfเป็นพารามิเตอร์แรกไปใช้ ดังนั้นควรจะเป็นเช่นเดียวกับx:bar(3,4)x.bar(x,3,4)


55
อ่า ... มันเป็นน้ำตาลเชิงวัตถุ
Jason S

7
เผง ในคู่มืออ้างอิงทั้งหมดสิ่งเดียวที่พวกเขาประกาศในที่นี้คือ "ไวยากรณ์ของลำไส้ใหญ่ใช้สำหรับการกำหนดวิธีการนั่นคือฟังก์ชันที่มีพารามิเตอร์เสริมโดยนัยของตนเอง" (5.0 Manual, ด้านล่างของ pdf หน้า 19)
BMitch

2
โอ้โห ... ฉันกำลังจะถามว่าเอกสารอย่างเป็นทางการอยู่ที่นี่ แต่คุณเอาชนะฉันมัน ทำได้ดีมาก :-)
Jason S

1
@keyle มันขึ้นอยู่กับselfวัตถุที่จะไปเป็นพารามิเตอร์แรกและค่าคุณสมบัติ
Hydroper

8
@keyle Colon ไวยากรณ์จะเร็วขึ้นเล็กน้อยหากวัตถุที่คุณโทรไม่ใช่เครื่องในท้องถิ่นเนื่องจากเครื่องเสมือนดึงข้อมูลได้เพียงครั้งเดียว โดยทั่วไปจุดไวยากรณ์เช่นobject.method(object,args)ดึงobjectสองครั้งในขณะที่object:method(arg)ดึงobjectเพียงครั้งเดียว ถ้าobjectเป็นโลก upvalue หรือสาขาที่โต๊ะแล้วจะเร็วกว่า: ไม่เคยได้เร็วกว่า ..:
negamartin

28

สำหรับคำจำกัดความมันเหมือนกับการระบุตนเองด้วยตนเอง - มันจะผลิตไบต์เดียวกันในการรวบรวม คือเป็นเช่นเดียวกับfunction object:method(arg1, arg2)function object.method(object, arg1, arg2)

ในการใช้งาน:คือเกือบจะเป็นเช่นเดียวกับ.- ชนิดพิเศษของสายจะถูกใช้ภายในเพื่อให้แน่ใจobjectและเป็นไปได้ใด ๆ ผลข้างเคียงของการคำนวณ / การเข้าถึงจะถูกคำนวณเพียงครั้งเดียว โทรศัพท์เป็นอย่างอื่นเช่นเดียวกับobject:method(arg1, arg2)object.method(object, arg1, arg2)


21

เพื่อความแม่นยำอย่างสมบูรณ์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)


คุณไม่ควรกังวลเกี่ยวกับสิ่งเหล่านี้จริงๆ หากคุณต้องมีบางสิ่งบางอย่างเพียงชะมัดผิดปกติกับสถาปัตยกรรมของคุณ
พูดว่า Reinstate Monica

2
ฉันจะบอกว่ามันเป็นอีกทางหนึ่ง รหัสที่ดีไม่ควรตั้งสมมติฐานเกี่ยวกับรายละเอียดการใช้งานของรหัสที่ไม่เกี่ยวข้อง การเรียกฟังก์ชั่นอาจจะใช่หรืออาจไม่ได้รับการบันทึกซึ่งไม่ได้หมายความว่าเป็นการดีที่จะเรียกพวกเขาบ่อยกว่าที่ต้องการ
DarkWiiPlayer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.