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

Posted

技术标签:

【中文标题】测试一个 Ruby 类是不是是另一个类的子类【英文标题】:Test whether a Ruby class is a subclass of another class测试一个 Ruby 类是否是另一个类的子类 【发布时间】:2011-05-31 12:55:50 【问题描述】:

我想测试一个类是否继承自另一个类,但似乎不存在这样的方法。

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

但我希望它已经存在。

【问题讨论】:

A.class #=&gt; Class。这就是 B.is_a? A 返回 false 的原因。 kind_of?怎么样 kind_of? 测试一个对象是否是一个类的instance。不是对象是否继承自一个类。 kind_of?is_a? 的别名 【参考方案1】:

只需使用&lt; 运算符

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

或使用&lt;= 运算符

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

【讨论】:

@Brian 因为is_a? 转换为的实例。 B 不是 A 的实例,B.new 是 (B.new.is_a? A # =&gt; true)。 嗯,奇怪的语法(这不是我的第一个猜测),但感谢您的澄清! 文档见Core API / Module / #<。 我对 Ruby 的爱恨交织仍在继续……为什么要为用于声明类关系的运算符提供不同的函数并提供两种不同的方法? @BenGotow - 1. 因为 【参考方案2】:

也有:

B.ancestors.include? A

这与B &lt; A 的(更短的)答案略有不同,因为B 包含在B.ancestors 中:

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

B < B
#=> false

B.ancestors.include? B
#=> true

这是否可取取决于您的用例。

【讨论】:

更具可读性:B &lt;= B(与B.ancestors.include? B 相同的结果)。 更新:前面的解决方案适用于 1.9+,而没有“祖先?”在 1.9 中。 这不会让不熟悉 ' @SimonLepkin 可能不会是“一会儿”,除非您可以体验到微秒的时间流逝。 ;) 是的,在幕后 include?&lt; 方法 loop through the ancestor chain。它在 C 中执行此操作,因此肯定比循环遍历 Ruby 数组要快……但实际上两者应该是无法区分的。 @JunanChakma 根据英文单词“ancestors”的定义,我同意返回值不应包含B。但确实如此。 method documentation 说,“返回 mod 中包含/前置的模块列表(包括 mod 本身)。”(强调我的)。我猜它在使用.include? 时为了方便起见包含了自己的类,但这只是我的猜测。

以上是关于测试一个 Ruby 类是不是是另一个类的子类的主要内容,如果未能解决你的问题,请参考以下文章

继承和接口

说说 Python 的继承

面向对象

Java 继承初探

ruby中的实例变量和类变量

阻塞IO非阻塞IO的区别