ทดสอบว่าคลาส Ruby เป็นคลาสย่อยของคลาสอื่นหรือไม่


187

ฉันต้องการทดสอบว่าคลาสสืบทอดจากคลาสอื่นหรือไม่ แต่ดูเหมือนว่าจะไม่มีวิธีสำหรับสิ่งนั้น

class A
end

class B < A
end

B.is_a? A 
=> false

B.superclass == A
=> true

การใช้งานเล็กน้อยของสิ่งที่ฉันต้องการจะเป็น:

class Class
  def is_subclass_of?(clazz)
    return true if superclass == clazz
    return false if self == Object
    superclass.is_subclass_of?(clazz)
  end
end

แต่ฉันคาดหวังว่าสิ่งนี้จะมีอยู่แล้ว


2
A.class #=> Class. นี่คือเหตุผลที่B.is_a? Aผลตอบแทนที่ผิดพลาด
เหวิน

แล้วkind_of?
akostadinov

1
kind_of?ทดสอบว่าวัตถุเป็นตัวอย่างของคลาสหรือไม่ ไม่ใช่ว่าวัตถุนั้นสืบทอดมาจากคลาสหรือไม่
ความสับสน

5
kind_of?เป็นนามแฝงของis_a?
คอเรย์เวิร์ด

คำตอบ:


355

เพียงแค่ใช้<โอเปอเรเตอร์

B < A # => true
A < A # => false

หรือใช้<=โอเปอเรเตอร์

B <= A # => true
A <= A # => true

13
@ Brian เพราะis_a?แปลว่าจะเป็นตัวอย่างของ Bไม่ได้เป็นตัวอย่างของA, B.newคือว่า ( B.new.is_a? A # => true)
Marcel Jackwerth

4
อืมไวยากรณ์แปลก ๆ (คงไม่เคยเดาออกมาก่อน) แต่ขอบคุณที่ให้ความกระจ่าง!
Brian Armstrong

2
สำหรับเอกสารดูแกน API / โมดูล / # <
webwurst

2
ความสัมพันธ์ความรัก / ความเกลียดชังของฉันกับทับทิมดำเนินต่อไป ... ทำไมจึงมีฟังก์ชั่นที่แตกต่างกันสำหรับผู้ปฏิบัติงานที่ใช้สำหรับการประกาศความสัมพันธ์ในชั้นเรียนและมีวิธีการทำสองวิธีที่แตกต่างกัน
Ben Gotow

4
@BenGotow - 1. เนื่องจาก <ไม่ใช่ตัวดำเนินการจึงเป็นวิธีการ 2. เนื่องจาก <เพียงตรวจสอบคลาสย่อยและ <= รวมถึงตัวเองด้วย
superluminary

59

ยังมีอยู่:

B.ancestors.include? A

สิ่งนี้แตกต่างจากคำตอบที่สั้นกว่าB < Aเนื่องจากBมีอยู่ในB.ancestors:

B.ancestors
#=> [B, A, Object, Kernel, BasicObject]

B < B
#=> false

B.ancestors.include? B
#=> true

ขึ้นอยู่กับกรณีการใช้งานของคุณ


24
อ่านง่ายขึ้น: B <= B(ผลลัพธ์เดียวกับB.ancestors.include? B)
Marcel Jackwerth

อัปเดต: โซลูชันก่อนหน้านี้ใช้งานได้กับ 1.9+ ทันทีในขณะที่ไม่มี "บรรพบุรุษ" ใน 1.9

8
สิ่งนี้จะไม่สับสนคนที่ไม่คุ้นเคยกับไวยากรณ์ '<' และด้วยเหตุนี้ฉันจึงชอบมัน
Asfand Qazi

2
@SimonLepkin อาจจะไม่ "ชั่วขณะ" เว้นแต่ว่าคุณจะได้รับการติ๊กด้วย microseconds ;) ใช่เบื้องหลังinclude?และ<วิธีการห่วงผ่านห่วงโซ่บรรพบุรุษ มันทำเช่นนี้ใน C ดังนั้นเร็วกว่าการวนลูปผ่านอาร์เรย์ Ruby แต่จริงๆแล้วทั้งสองควรแยกไม่ออก
Phrogz

1
@JunanChakma ตามวิธีการที่ภาษาอังกฤษคำว่า "บรรพบุรุษ" Bหมายผมยอมรับว่าค่าตอบแทนไม่ควรมี แต่มันก็เป็นเช่นนั้น เอกสารวิธีการกล่าวว่า"ผลตอบแทนรายชื่อของโมดูลรวม / ใช้ได้ใน mod ( รวมทั้ง mod ตัวเอง )." (เน้นที่เหมือง) ฉันเดาว่ามันรวมคลาสของตัวเองเพื่อความสะดวกเมื่อใช้.include?แต่นั่นเป็นเพียงการคาดเดาในส่วนของฉัน
Phrogz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.