Uji apakah kelas Ruby adalah subkelas dari kelas lain

187

Saya ingin menguji apakah suatu kelas mewarisi dari kelas lain, tetapi sepertinya tidak ada metode untuk itu.

class A
end

class B < A
end

B.is_a? A 
=> false

B.superclass == A
=> true

Implementasi sepele dari apa yang saya inginkan adalah:

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

tapi saya berharap ini sudah ada.

Kebingungan
sumber
2
A.class #=> Class. Inilah sebabnya mengapa B.is_a? Amengembalikan false.
Wen
bagaimana dengankind_of?
akostadinov
1
kind_of?menguji apakah suatu objek adalah turunan dari kelas. Bukan apakah objek tersebut diturunkan dari suatu kelas.
Kebingungan
5
kind_of?adalah alias dariis_a?
coreyward

Jawaban:

355

Cukup gunakan <operator

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

atau gunakan <=operator

B <= A # => true
A <= A # => true
Marcel Jackwerth
sumber
13
@Brian Karena is_a?diterjemahkan ke adalah dari . Bbukan turunan dari A, B.newis though ( B.new.is_a? A # => true).
Marcel Jackwerth
4
Hmm, sintaks aneh (tidak akan menjadi tebakan pertama saya), tapi terima kasih atas klarifikasi!
Brian Armstrong
2
Untuk dokumentasi lihat Core API / Module / # < .
webwurst
2
Hubungan cinta / benci saya dengan Ruby berlanjut ... Mengapa menyediakan fungsi yang berbeda untuk operator yang digunakan untuk menyatakan hubungan kelas DAN menyediakan dua cara berbeda untuk melakukannya?
Ben Gotow
4
@ BenGotow - 1. Karena <bukan operator, ini adalah metode. 2. Karena <hanya memeriksa subclass, dan <= juga termasuk diri.
superluminary
59

Juga tersedia:

B.ancestors.include? A

Ini sedikit berbeda dari jawaban (lebih pendek) B < Akarena Btermasuk dalam B.ancestors:

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

B < B
#=> false

B.ancestors.include? B
#=> true

Apakah ini diinginkan atau tidak tergantung pada kasus penggunaan Anda.

Phrogz
sumber
24
Lebih mudah dibaca: B <= B(hasil yang sama seperti B.ancestors.include? B).
Marcel Jackwerth
Pembaruan: Solusi segera sebelumnya berfungsi dengan 1.9+ sedangkan tidak ada "leluhur?" dalam 1.9.
8
Ini tidak akan membingungkan orang yang tidak terbiasa dengan sintaks '<', dan untuk alasan itu saya lebih suka.
Asfand Qazi
2
@SimonLepkin Mungkin bukan "sementara", kecuali jika Anda dapat mengalami detak detik. ;) Ya, di belakang layar metode include?dan loop melalui rantai leluhur . Ini melakukan ini dalam C, jadi pasti lebih cepat daripada perulangan melalui array Ruby ... tapi praktis keduanya tidak bisa dibedakan. <
Phrogz
1
@JunanChakma Berdasarkan pada bagaimana kata dalam bahasa Inggris "nenek moyang" didefinisikan, saya setuju bahwa nilai balik tidak boleh dimasukkan B. Tapi itu benar. The metode dokumentasi mengatakan, "Pengembalian daftar modul termasuk / prepended di mod ( termasuk mod sendiri )." (penekanan milikku). Saya kira itu termasuk kelasnya sendiri untuk kenyamanan saat menggunakan .include?, tapi itu hanya spekulasi di pihak saya.
Phrogz