测试Ruby类是否是另一个类的子类

Con*_*ion 175 ruby inheritance subclass superclass

我想测试一个类是否继承自另一个类,但似乎没有一个方法.

class A
end

class B < A
end

B.is_a? A 
=> false

B.superclass == A
=> true
Run Code Online (Sandbox Code Playgroud)

我想要的一个微不足道的实现是:

class Class
  def is_subclass_of?(clazz)
    return true if superclass == clazz
    return false if self == Object
    superclass.is_subclass_of?(clazz)
  end
end
Run Code Online (Sandbox Code Playgroud)

但我希望这已经存在了.

Mar*_*rth 339

只需使用<操作员即可

B < A # => true
A < A # => false
Run Code Online (Sandbox Code Playgroud)

或使用<=运营商

B <= A # => true
A <= A # => true
Run Code Online (Sandbox Code Playgroud)

  • @Brian因为`is_a?`转换为*是*的实例.`B`不是'A`的实例,`B.new`是(`B.new.is_a?A#=> true`). (13认同)
  • 嗯,奇怪的语法(不是我的第一个猜测),但谢谢你的澄清! (4认同)
  • @BenGotow - 1.因为<不是运算符,所以它是一种方法.2.因为<只检查子类,<=也包括self. (4认同)
  • 有关文档,请参阅[Core API/Module /#<](http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-3C). (2认同)
  • 我与Ruby的爱/恨关系继续......为什么为用于声明类关系的运算符提供不同的函数并提供两种不同的方法呢? (2认同)

Phr*_*ogz 56

也提供:

B.ancestors.include? A
Run Code Online (Sandbox Code Playgroud)

这与(较短的)答案略有不同,B < A因为B它包含在B.ancestors:

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

B < B
#=> false

B.ancestors.include? B
#=> true
Run Code Online (Sandbox Code Playgroud)

这是否可取取决于您的使用案例.

  • 更易读:`B <= B`(与`B.ancestors.include?B`相同的结果). (24认同)
  • 这不会混淆不熟悉'<'语法的人,因此我更喜欢它. (8认同)
  • @SimonLepkin可能不是"一段时间",除非你可以体验微秒.;)是的,幕后的`include?`和`<`方法[循环通过祖先链](https://github.com/ruby/ruby/blob/trunk/class.c#L1023).它在C中执行此操作,因此肯定比循环遍历Ruby数组更快......但实际上这两者应该是难以区分的. (2认同)
  • @JunanChakma 根据英语单词“ancestors”的定义,我同意返回值不应该包含`B`。但确实如此。[方法文档](http://ruby-doc.org/core-2.5.0/Module.html#method-i-ancestors)说,_“返回mod中包含/前置的模块列表(**包括mod 本身**)。“_(强调我的)。我猜测它包含自己的类是为了在使用“.include?”时方便,但这只是我的猜测。 (2认同)