Ruby sınıfının başka bir sınıfın alt sınıfı olup olmadığını test edin


187

Bir sınıfın başka bir sınıftan miras alıp almadığını test etmek istiyorum, ancak bunun için bir yöntem yok gibi görünüyor.

class A
end

class B < A
end

B.is_a? A 
=> false

B.superclass == A
=> true

İstediğim önemsiz bir uygulama olurdu:

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

ama bunun zaten var olmasını beklerdim.


2
A.class #=> Class. Bu yüzden B.is_a? Ayanlış döndürür.
Wen

ne dersinkind_of?
akostadinov

1
kind_of?bir nesnenin bir sınıf örneği olup olmadığını test eder . Nesnenin bir sınıftan miras alıp almadığı değil.
Karışıklık

5
kind_of?bir takma adıis_a?
coreyward

Yanıtlar:


355

Sadece <operatörü kullanın

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

veya <=operatörü kullanın

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

13
@Brian nedeniyle is_a?çevirir arasında örneğidir . Bbir örneği değil A, B.newama bir ( B.new.is_a? A # => true).
Marcel Jackwerth

4
Hmm, garip sözdizimi (ilk tahminim olmazdı), ama açıklama için teşekkürler!
Brian Armstrong

2
Dokümantasyon için bkz. Core API / Modül / # < .
webwurst

2
Ruby ile olan aşk / nefret ilişkim devam ediyor… Neden sınıf ilişkilerini bildirmek için kullanılan bir operatör için farklı bir işlev sunmalı ve bunu yapmanın iki farklı yolunu sunalım?
Ben Gotow

4
@BenGotow - 1. <bir operatör olmadığından, bir yöntemdir. 2. Çünkü <sadece bir alt sınıfı kontrol eder ve <= aynı zamanda benliği de içerir.
superluminary

59

Ayrıca mevcut:

B.ancestors.include? A

Arasında (kısa) cevabını biraz Bu farklılık B < Anedeniyle Bdahildir B.ancestors:

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

B < B
#=> false

B.ancestors.include? B
#=> true

Bunun istenip istenmeyeceği kullanım durumunuza bağlıdır.


24
Daha okunabilir: B <= B(ile aynı sonuç B.ancestors.include? B).
Marcel Jackwerth

Güncelleme: Hemen önceki çözüm 1.9+ ile çalışır, oysa "atalar?" 1.9.

8
Bu, '<' sözdizimine aşina olmayan insanları karıştırmayacak ve bu nedenle tercih ediyorum.
Asfand Qazi

2
@SimonLepkin Eğer mikrosaniye yaşayamazsanız, muhtemelen "bir süre" değil. ;) Evet, perde arkası include?ve <yöntemleri , ata zincirinden geçer . Bunu C'de yapar, Ruby dizisinde döngü yapmaktan çok daha hızlıdır ... ancak pratik olarak ikisi ayırt edilemez olmalıdır.
Phrogz

1
@JunanChakma İngilizce "atalar" kelimesinin nasıl tanımlandığına bağlı olarak, dönüş değerinin içermemesi gerektiğini kabul ediyorum B. Ama öyle. Yöntemiyle ilgili belgeler , diyor "(mod önüne modüllerinin bir listesi dahil İade / mod kendisi dahil )." (benimkini vurgulayın). Sanırım kullanırken kolaylık sağlamak için kendi sınıfını içeriyor .include?, ama bu sadece benim düşüncem.
Phrogz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.