测试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?
akostadinov 2014年

1
kind_of?测试对象是否是类的实例。不是对象是否从类继承。
困惑,2014年

5
kind_of?is_a?
coreyward

Answers:


355

只需使用<运算符

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

或使用<=运算符

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

13
@Brian因为is_a?转换为是的实例B不是的实例AB.new而是(B.new.is_a? A # => true)。
马塞尔·杰克韦斯

4
嗯,奇怪的语法(这不是我的第一个猜测),但感谢您的澄清!
Brian Armstrong

2
有关文档,请参见Core API /模块/#<
webwurst 2013年

2
我对Ruby的爱恨关系仍在继续……为什么要为用于声明类关系的运算符提供不同的功能,并提供两种不同的实现方式?
Ben Gotow

4
@BenGotow-1.因为<不是运算符,所以它是一种方法。2.因为<仅检查子类,并且<=也包括self。
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 2010年

更新:之前的解决方案适用于1.9+,而没有“祖先”?在1.9中。

8
这不会使不熟悉'<'语法的人感到困惑,因此我更喜欢它。
Asfand Qazi

2
@SimonLepkin大概不是“一会儿”,除非您会经历微秒的滴答声。;)是,在幕后,include?and <方法在祖先链中循环。它在C中执行此操作,因此肯定比在Ruby数组中循环要快...但是实际上两者应该是无法区分的。
Phrogz

1
@JunanChakma基于英语单词“ ancestors”的定义,我同意返回值不应包含B。但是确实如此。该方法的文档说,“返回包含模块的列表/在MOD预先考虑(包括MOD本身)。” (强调我的)。我猜想它在使用时会包含自己的类以方便使用.include?,但这只是我的推测。
Phrogz '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.