Проверьте, является ли класс 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возвращает false.
Вэнь

а как жеkind_of?
акостадинов

1
kind_of?проверяет, является ли объект экземпляром класса. Не наследует ли объект от класса.
Беспорядок

5
kind_of?это псевдонимis_a?
coreyward

Ответы:


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).
Марсель Джекверт

4
Хм, странный синтаксис (не был бы моим первым предположением), но спасибо за разъяснение!
Брайан Армстронг

2
Для документации см. Core API / Module / # < .
webwurst

2
Мои отношения любви / ненависти с Руби продолжаются ... Зачем предоставлять оператору другую функцию, используемую для объявления отношений класса И два разных способа сделать это?
Бен Готов

4
@BenGotow - 1. Потому что <не оператор, это метод. 2. Потому что <проверяет только подкласс, а <= также включает себя.
Сверхсветовой

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).
Марсель Джекверт

Обновление: непосредственно предшествующее решение работает с 1.9+, в то время как нет "предков?" в 1.9.

8
Это не смущает людей, не знакомых с синтаксисом «<», и по этой причине я предпочитаю его.
Асфанд Кази

2
@SimonLepkin Вероятно, не «на время», если только вы не испытываете микросекунды. ;) Да, за кулисами методы include?и проходят через цепочку предков . Он делает это в C, так что, безусловно, быстрее, чем цикл по массиву Ruby ... но практически оба должны быть неразличимы. <
Phrogz

1
@JunanChakma Исходя из того, как определено английское слово «предки», я согласен, что возвращаемое значение не должно включать B. Но это так. Документация по методу гласит: «Возвращает список модулей, включенных / добавленных в мод ( включая сам мод )». (акцент мой). Я предполагаю, что он включает в себя собственный класс для удобства использования .include?, но это всего лишь предположение с моей стороны.
Phrogz
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.