ทำไม Ruby Setters จึงต้องการการระบุ self.
ภายในคลาส?
ในโลกของภาษาโปรแกรมมิง ภาษาต่าง ๆ มีไวยากรณ์และกฎเฉพาะของตัวเองที่กำหนดว่าโค้ดถูกสร้างและดำเนินการอย่างไร Ruby ซึ่งเป็นภาษาโปรแกรมมิงแบบไดนามิกและเชิงวัตถุ มีลักษณะเฉพาะที่ไม่เหมือนใครเมื่อพูดถึงวิธีการ setter โดยเฉพาะอย่างยิ่ง ผู้ตั้งค่า Ruby—ไม่ว่าจะถูกสร้างขึ้นโดยการใช้ attr_accessor
หรือถูกกำหนดขึ้นเอง จะต้องการการระบุ self.
เมื่อถูกเข้าถึงจากภายในคลาสเอง บทความนี้จะเจาะลึกถึงเหตุผลเบื้องหลังข้อกำหนดนี้และสำรวจผลกระทบในการเขียนโปรแกรม Ruby
ปัญหา: ความคลุมเครือของวิธีการ Setter
เมื่อคุณกำลังเขียนคลาส Ruby คุณอาจสังเกตเห็นว่าในขณะที่วิธีการของอินสแตนซ์สามารถถูกเรียกโดยไม่ต้องการการระบุ แต่ setter กลับเสนอกรณีที่แตกต่าง ลองมาทำความเข้าใจกับจุดสำคัญเกี่ยวกับการระบุวิธีการ:
- ภาษาโปรแกรมมิงบางภาษา เช่น C# และ Java ไม่ต้องการ
this
หรือself
สำหรับการเรียกวิธีการ ซึ่งทำให้โครงสร้างทางไวยากรณ์ของพวกเขาง่ายขึ้นในหลายกรณี - ภาษาอื่น ๆ รวมถึง Perl และ JavaScript จำเป็นต้องใช้
self
หรือthis
สำหรับวิธีการทั้งหมดอย่างสม่ำเสมอ - Ruby อยู่ในระหว่าง—เพียงแต่วิธีการ setter ของมันเท่านั้นที่บังคับใช้การระบุ
self.
ซึ่งนำไปสู่ความสับสนที่อาจเกิดขึ้น
ตัวอย่างใน Ruby
เพื่อเน้นย้ำพฤติกรรมนี้ ให้พิจารณาคลาส Ruby ต่อไปนี้:
class A
def qwerty; @q; end # manual getter
def qwerty=(value); @q = value; end # manual setter
def asdf; self.qwerty = 4; end # "self." is necessary
def xxx; asdf; end # no need for "self."
def dump; puts "qwerty = #{qwerty}"; end
end
a = A.new
a.xxx
a.dump
หากคุณลบ self
ออกจาก self.qwerty = 4
ในวิธีการ asdf
Ruby จะเกิดข้อผิดพลาด ซึ่งบ่งบอกว่าไม่สามารถระบุวิธีการ setter ที่ต้องการได้ ซึ่งเน้นย้ำถึงความจำเป็นในการระบุ self.
สำหรับวิธีการ setter ที่อาจเกิดความคลุมเครือ
เข้าใจความต้องการ
ทำไมต้อง self.
?
ข้อกำหนดของ self.
ใน Ruby หมุนรอบการจัดการความคลุมเครือ เมื่อคุณเขียนคำแถลงเช่น qwerty = 4
Ruby จำเป็นต้องแยกความแตกต่างระหว่างสองความเป็นไปได้:
- การเรียกวิธีการ: อาจกำลังพยายามเรียกวิธีการ setter ที่ชื่อ
qwerty=
- การกำหนดตัวแปรท้องถิ่น: อาจกำลังประกาศตัวแปรท้องถิ่นใหม่ที่ชื่อ
qwerty
เพื่อลดความคลุมเครือนี้อย่างชาญฉลาด การกำหนดค่าทุกครั้งจะต้องทำการตรวจสอบว่ามีวิธีการที่ชื่อดังกล่าวมีอยู่ในเวลาที่ทำการกำหนดหรือไม่ อย่างไรก็ตาม สิ่งนี้อาจส่งผลกระทบต่อประสิทธิภาพและประสิทธิผลในขณะทำงาน
การเปรียบเทียบกับ C#
ในทางตรงกันข้าม C# ใช้โมเดลที่อนุญาตให้เรียกใช้ setter โดยไม่ต้องการการระบุ this
ตัวอย่างเช่น:
public class A {
public int qwerty { get; set; }
public void asdf() { qwerty = 4; } // C# setters work without "this."
}
การออกแบบทางไวยากรณ์นี้ทำให้โค้ดง่ายขึ้น แต่ก็มีความซับซ้อนในตัวเอง ใน C# ชื่อของตัวแปรและวิธีการจะถูกเข้าใจตามบริบทโดยคอมไพล์เลอร์ จึงช่วยลดความคลุมเครือบางประการที่มีอยู่ใน Ruby
เมื่อใดที่ต้องการ self.
ใน Ruby?
นอกจากวิธีการ setter แล้ว ยังมีกรณีอื่น ๆ ใน Ruby ที่จำเป็นต้องมี self.
เพื่อแยกความแตกต่างระหว่างการเรียกวิธีการและการกำหนดตัวแปร:
- เมื่อตัวแปรท้องถิ่นมีชื่อเดียวกันกับวิธีการ: หากคุณมีทั้งวิธีการและตัวแปรที่ชื่อ
foo
การเรียกfoo
จะทำให้เรียกวิธีการ ขณะที่foo = value
จะทำการกำหนดตัวแปรท้องถิ่น - เมื่อต้องการทำให้ชัดเจน: การใช้
self.
ยังสามารถทำหน้าที่เพื่อทำให้ชัดเจนแก่ผู้อ่านว่าคุณตั้งใจจะเรียกวิธีการแทนที่จะกำหนดตัวแปรท้องถิ่น
สรุป
ความจำเป็นในการระบุ self.
ใน Ruby setters นำมาซึ่งการอภิปรายที่น่าสนใจเกี่ยวกับการออกแบบภาษาโปรแกรมมิงและการแก้ปัญหาความคลุมเครือ การเข้าใจคุณลักษณะเหล่านี้ไม่เพียงแต่ช่วยให้คุณเขียนโค้ด Ruby ได้ดีขึ้น แต่ยังช่วยให้คุณเข้าใจลึกซึ้งยิ่งขึ้นเกี่ยวกับวิธีการที่ภาษาต่าง ๆ เข้าหาโครงสร้างที่คล้ายกัน ในขณะที่มันอาจทำให้คุณต้องพิมพ์อักขระเพิ่มเติม แต่มันทำให้เกิดความชัดเจนและมีเจตนาในการเรียกวิธีการ ซึ่งเป็นหลักการพื้นฐานของปรัชญาการออกแบบของ Ruby ดังนั้น ครั้งถัดไปที่คุณอยู่ในระหว่างการเขียนโค้ด Ruby ให้จำไว้ว่า self.
ไม่ใช่เพียงข้อกำหนด—มันเป็นกุญแจสำคัญในการหลีกเลี่ยงความคลุมเครือและเสริมสร้างความสามารถในการอ่านโค้ด