คลาสซิงเกิลใน Ruby เป็นคลาสในตัวเองหรือไม่? มันเป็นเหตุผลว่าทำไมวัตถุทั้งหมดเป็นของ "คลาส"? แนวคิดนั้นคลุมเครือแต่ฉันเชื่อว่ามันมีส่วนเกี่ยวข้องกับสาเหตุที่ฉันสามารถกำหนดเมธอดคลาสได้เลย ( class foo; def foo.bar ...
)
คลาส Singleton ใน Ruby คืออะไร?
คลาสซิงเกิลใน Ruby เป็นคลาสในตัวเองหรือไม่? มันเป็นเหตุผลว่าทำไมวัตถุทั้งหมดเป็นของ "คลาส"? แนวคิดนั้นคลุมเครือแต่ฉันเชื่อว่ามันมีส่วนเกี่ยวข้องกับสาเหตุที่ฉันสามารถกำหนดเมธอดคลาสได้เลย ( class foo; def foo.bar ...
)
คลาส Singleton ใน Ruby คืออะไร?
คำตอบ:
ประการแรกคำจำกัดความเล็กน้อย: วิธีเดี่ยวคือวิธีการที่กำหนดไว้สำหรับวัตถุเดียวเท่านั้น ตัวอย่าง:
irb(main):001:0> class Foo; def method1; puts 1; end; end
=> nil
irb(main):002:0> foo = Foo.new
=> #<Foo:0xb79fa724>
irb(main):003:0> def foo.method2; puts 2; end
=> nil
irb(main):004:0> foo.method1
1
=> nil
irb(main):005:0> foo.method2
2
=> nil
irb(main):006:0> other_foo = Foo.new
=> #<Foo:0xb79f0ef4>
irb(main):007:0> other_foo.method1
1
=> nil
irb(main):008:0> other_foo.method2
NoMethodError: undefined method `method2' for #<Foo:0xb79f0ef4>
from (irb):8
วิธีการอินสแตนซ์เป็นวิธีการของคลาส (กล่าวคือกำหนดไว้ในนิยามของคลาส) เมธอดคลาสคือเมธอดเดี่ยวบนClass
อินสแตนซ์ของคลาส - ไม่ได้กำหนดไว้ในนิยามของคลาส แต่ถูกกำหนดไว้ในคลาสซิงเกิลตันของอ็อบเจ็กต์
irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false
class << obj
คุณสามารถเปิดชั้นเดี่ยวของวัตถุที่มีไวยากรณ์ ที่นี่เราจะเห็นว่าคลาสซิงเกิลตันนี้เป็นที่ที่กำหนดเมธอด singleton:
irb(main):012:0> singleton_class = ( class << foo; self; end )
=> #<Class:#<Foo:0xb79fa724>>
irb(main):013:0> singleton_class.method_defined? :method1
=> true
irb(main):014:0> singleton_class.method_defined? :method2
=> true
irb(main):015:0> other_singleton_class = ( class << other_foo; self; end )
=> #<Class:#<Foo:0xb79f0ef4>>
irb(main):016:0> other_singleton_class.method_defined? :method1
=> true
irb(main):017:0> other_singleton_class.method_defined? :method2
=> false
ดังนั้นวิธีการอื่นในการเพิ่มวิธีการ singleton ให้กับวัตถุคือการกำหนดด้วยคลาส singleton ของวัตถุที่เปิดอยู่
irb(main):018:0> class << foo; def method3; puts 3; end; end
=> nil
irb(main):019:0> foo.method3
3
=> nil
irb(main):022:0> Foo.method_defined? :method3
=> false
สรุป:
Class
Ruby ให้วิธีการกำหนดวิธีการที่เฉพาะเจาะจงสำหรับวัตถุเฉพาะและวิธีการดังกล่าวเรียกว่า Singleton Methods เมื่อคนหนึ่งประกาศเมธอด singleton บนวัตถุ Ruby จะสร้างคลาสโดยอัตโนมัติเพื่อเก็บเฉพาะเมธอด singleton คลาสที่สร้างขึ้นใหม่เรียกว่าคลาส Singleton
foo = Array.new
def foo.size
"Hello World!"
end
foo.size # => "Hello World!"
foo.class # => Array
#Create another instance of Array Class and call size method on it
bar = Array.new
bar.size # => 0
คลาส Singleton เป็นคลาสที่ไม่ระบุชื่อเฉพาะของออบเจ็กต์ที่สร้างขึ้นโดยอัตโนมัติและแทรกลงในลำดับชั้นการสืบทอด
singleton_methods
สามารถเรียกบนอ็อบเจกต์เพื่อรับรายชื่อของเมธอด singleton ทั้งหมดบนอ็อบเจ็กต์
foo.singleton_methods # => [:size]
bar.singleton_methods # => []
นี้บทความจริงๆช่วยให้ฉันเข้าใจเรียนซิงเกิลในรูบีและมีโค้ดตัวอย่างที่ดี
เช่นเดียวกับการอัปเดตเป็นคำตอบ @Pistos จากเวอร์ชัน 1.9.2 Ruby จะเพิ่มไวยากรณ์ใหม่ไปจนถึงการรับคลาสซิงเกิลตัน
singleton_class = ( class << foo; self; end )
สามารถแทนที่ได้ด้วย:
singleton_class = foo.singleton_class
วิธีคิดเชิงปฏิบัติ / การกระทำที่เป็นประโยชน์มากที่สุดในการคิด (IMHO) คือ: เป็นห่วงโซ่การสืบทอดหรือลำดับการค้นหาวิธีการ / การแก้ไข ภาพนี้อาจช่วยได้
http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/
นี่คือ r 1.9 ซึ่งแตกต่างจากคลาสในตัวและคลาสที่ผู้ใช้กำหนดเอง: ฉันยังย่อยอันนี้อยู่
http://d.hatena.ne.jp/sumim/20080111/p1
นอกจากนี้ฉันคิดว่าการใช้คำที่สับสนคือ "Singleton object" ซึ่งเป็นแนวคิดที่แตกต่างกัน อ็อบเจ็กต์ singleton มาจากคลาสที่มีตัวสร้าง / วิธีการสร้างอินสแตนซ์แทนเพื่อให้คุณสามารถจัดสรรคลาสนั้นได้
คลาสซิงเกิลตันในคำที่ง่ายที่สุดคือทับทิมคลาสพิเศษแส้ขึ้นกับเมธอดโฮสต์ที่กำหนดไว้ในแต่ละออบเจ็กต์ ในทับทิมเป็นไปได้ที่จะกำหนดวิธีการบนวัตถุแต่ละชิ้นที่มีลักษณะเฉพาะสำหรับวัตถุนั้นเพียงอย่างเดียว ตัวอย่างเช่นพิจารณาสิ่งต่อไปนี้ด้านล่าง
class User; end
user = User.new
def user.age
"i'm a unique method"
end
user1 = User.new
user.age #"i'm a unique method"
user1.age # NoMethodError (undefined method `age' for #<User:0x0000559c66ab7338>)
ดังที่คุณเห็นด้านบนอ็อบเจ็กต์ user1 ไม่ตอบสนองต่อเมธอด 'age' เนื่องจากเป็นเมธอดเดี่ยวซึ่งเป็นวิธีการที่กำหนดโดยไม่ซ้ำกันบนอ็อบเจ็กต์ผู้ใช้ เพื่อให้สิ่งนี้เกิดขึ้น Ruby จึงสร้างคลาสพิเศษที่เรียกว่าคลาส singleton หรือ eigenclass เพื่อโฮสต์วิธีการเฉพาะนี้ คุณสามารถตรวจสอบได้โดยดำเนินการดังต่อไปนี้:
user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>
คุณยังสามารถถามทับทิมว่าพบเมธอด 'age' ที่นี่หรือไม่โดยใช้ method object เพื่อค้นหาว่าเมธอด 'age' ถูกกำหนดไว้ที่ใด เมื่อคุณทำสิ่งนี้คุณจะเห็นว่าคลาส singleton มีวิธีการนั้น
user_singleton_class = user.method(:age).owner # #<Class:#<User:0x0000559c66b47c58>>
user.method(:age).owner == user.singleton_class # true
user_singleton_class.instance_methods(false) # [:age]
โปรดทราบว่าในขณะที่คลาสซิงเกิลตันใช้วิธีการแบบซิงเกิลตันเป็นวิธีอินสแตนซ์
user.singleton_methods == user_singleton_class.instance_methods(false) # true