หากคุณกำลังเรียน Ruby คุณอาจพบว่าการใช้คีย์เวิร์ด "self" น่าสับสนมาก
มันทำงานอย่างไร?
self คืออะไร จริงๆ แล้ว?
มันคือ คีย์เวิร์ดของ Ruby ที่ให้คุณเข้าถึงออบเจ็กต์ปัจจุบัน (current object)
หากคุณไม่รู้ว่าออบเจ็กต์คืออะไร ดูวิดีโอที่ผมทำไว้ให้คุณ มันเกี่ยวกับ Object-Oriented Programming
"ออบเจ็กต์ปัจจุบัน" นี้ขึ้นอยู่กับบริบท (context)
บริบท?
ใช่ บริบทคือที่ที่โค้ดของคุณอยู่ในเวลาใดเวลาหนึ่ง
ตัวอย่าง:
หากโค้ดของคุณอยู่ภายใน instance method self คือ อินสแตนซ์ ของคลาสนั้น กล่าวคือ self คือออบเจ็กต์
คุณสามารถเห็นได้ด้วยตัวเอง
รันโค้ดนี้:
def coffee puts self end coffee # main
โค้ดนี้กำหนดและเรียกเมธอด coffee ซึ่งพิมพ์ค่าของ self
ทำไมมันพิมพ์ main?
เพราะนี่คือชื่อของออบเจ็กต์ระดับบนสุด (top-level object) มันคือออบเจ็กต์ที่คุณจะพบเมธอดทั้งหมดที่กำหนด นอก คลาส
เหมือนเมธอด coffee ของเราที่นี่
แตถ้าคุณกำหนดเมธอดภายในคลาสชื่อ Cat แล้ว self จะเป็นออบเจ็กต์ Cat
เห็นได้ที่นี่:
class Cat
def meow
puts self
end
end
Cat.new.meow # <Cat:0x7a14c5>
จากตัวอย่างเหล่านี้ เราสามารถบอกได้ว่าค่าของ self เปลี่ยนไปขึ้นอยู่กับที่คุณใช้มัน
ตอนนี้:
ผมเชื่อว่าคุณสามารถเข้าใจอะไรก็ตามได้ดีขึ้น โดยการเข้าใจวัตถุประสงค์ของมัน
ทำไม self จึงมีประโยชน์?
มาดูตัวอย่างบ้าง
การใช้ Self เพื่อความชัดเจน (Disambiguation)
การใช้งาน self ที่ปฏิบัติจริงหนึ่งคือ เพื่อแยกแยะความแตกต่างระหว่างเมธอดและตัวแปรท้องถิ่น (local variable)
มันไม่ใช่ความคิดที่ดีที่จะตั้งชื่อตัวแปรและเมธอดเหมือนกัน แตถ้าคุณต้องทำงานกับสถานการณ์นั้น คุณจะสามารถเรียกเมธอดด้วย self.method_name
นี่คือสิ่งที่ผมหมายถึง:
class Example
def do_something
banana = "variable"
puts banana
puts self.banana
end
def banana
"method"
end
end
Example.new.do_something
# "variable" => puts banana
# "method" => puts self.banana
ที่นี่เรามีตัวแปรท้องถิ่น banana ภายในเมธอด do_something แตเราก็มีเมธอด banana ด้วย
ตัวแปรท้องถิ่นมีความสำคัญกว่า (takes priority)
นั่นคือเหตุผลที่เราต้องใช้ self ที่นี่ หากเราต้องการ เรียก เมธอด banana แทนที่จะ พิมพ์ ค่าของตัวแปร banana
ต่อไป:
มาดูกรณีใช้งานที่พบบ่อยกว่า... การกำหนดเมธอดระดับคลาส (Class-level methods)!
การใช้ Self เพื่อกำหนดเมธอดระดับคลาส
การใช้ self หมายเลข ONE ไม่ต้องสงสัย คือ การกำหนดเมธอดระดับคลาส
ผมมั่นใจว่าคุณเคยเห็นมัน
นี่คือการกำหนดเมธอด def self.method_name
เหมือนนี้:
class Salad
def self.buy_olive_oil
# ...
end
end
Salad.buy_olive_oil
self ที่นี่เทียบเท่ากับ Salad ชื่อคลาส
ทำไมสิ่งนี้จึงมีประโยชน์?
เพราะเราไม่ต้องใช้ชื่อคลาสสำหรับการกำหนดเมธอดทุกตัว ทำให้โค้ดของเราง่ายต่อการเปลี่ยนแปลงหากเราเปลี่ยนคลาส
มันยังทำให้โค้ดมีเสียงน้อยลง (less noisy) และอ่านง่ายขึ้น
นั่นคือเหตุผลที่เราเขียน def self.buy_olive_oil แทน def Salad.buy_olive_oil
การใช้งาน Self อื่นๆ
ใช่!
ยังมีการใช้งาน self อื่นๆ อีกมาก ดังนั้นมันจึงเป็นสิ่งที่คุ้มค่าที่จะคุ้นเคย
ตัวอย่าง:
คุณสามารถใช้มันในเมธอดเพื่อเปรียบเทียบออบเจ็กต์ปัจจุบันกับออบเจ็กต์อื่น
อย่างนี้:
def ==(other) self == other end
คุณยังสามารถใช้ self เพื่อจุดประสงค์ดีบัก (debugging) เพื่อค้นหาว่าคุณกำลังทำงานกับออบเจ็กต์ไหน
แบบนี้:
p self
หรือคุณสามารถใช้มันเป็นค่าส่งคืน (return value) เพื่อนำรูปแบบการออกแบบ (design patterns) เช่น Builder Design Pattern ไปใช้
ตัวอย่าง:
class Salad
def initialize
@ingredients = []
end
def add_nuts
@ingredients << :nuts
self
end
end
my_salad = Salad.new.add_nuts
สรุป นี่คือรายการการใช้งาน self ที่มีประโยชน์:
- กำหนดเมธอดระดับคลาส
- ใช้เมธอดอินสแตนซ์เมื่อคุณมีตัวแปรท้องถิ่นชื่อเดียวกัน
- ส่งคืน Self (builder pattern)
- ดีบัก (Debugging)
- เปรียบเทียบออบเจ็กต์ (==)
- Default receiver of method calls
Self vs Itself
อีกหนึ่งสิ่งที่เราควรดูก่อนจบหัวข้อนี้
เมธอด Kernel#itself
มันคือเมธอดที่คุณสามารถเรียกบนออบเจ็กต์ และออบเจ็กต์จะส่งคืนตัวมันเอง
ตัวอย่าง:
[1,2,3,nil].select(&:itself) # [1, 2, 3]
ตัวอย่างนี้กรองค่า nil และ false ออก
การเข้าใจความแตกต่าง:
selfเป็นคีย์เวิร์ด ค่าขึ้นอยู่กับ ที่ไหน ที่คุณใช้มันitselfเป็นเมธอด ค่าขึ้นอยู่กับ อะไร ออบเจ็กต์ที่คุณใช้มัน (ใน1.itself,1คือออบเจ็กต์)
หวังว่าจะมีประโยชน์
สรุป
คุณได้เรียนรู้เกี่ยวกับคีย์เวิร์ด self ของ Ruby ทุกอย่างแล้ว คือ มันคืออะไร ทำไมมันมีประโยชน์ และวิธีใช้มัน
ตอนถึงคุณลองทำดูสิ
ขอบคุณที่อ่าน! 🙂