2

前一个问题的答案中所述B < A这是确定一个类是否是另一个类的最简单方法。B但是,当是单例类(即特征类)时,这在 Ruby 1.8(也是 REE 1.8)中似乎失败了。为了显示:

class A; end
class B < A; end

b = B.new

B.ancestors                         # => [B, A, Object, Kernel] (also BasicObject in 1.9)
(class << b; self; end).ancestors   # => [B, A, Object, Kernel] (also BasicObject in 1.9)

B < A                               # => true
(class << b; self; end) < A         # => true in 1.9; false in 1.8

如您所见,即使A被列为单例类 ( class << b; self; end)的祖先,false当您检查它是否是ARuby 1.8 中的子类时,它也会返回(但true在 1.9 中正确返回)。遵循#superclass链条似乎显示了为什么会这样:

B.superclass
  # => A

(class << b; self; end).superclass
  # => B in 1.9
  # => singleton class of B in 1.8

(class << b; self; end).superclass.superclass
  # => A in 1.9
  # => singleton class of Class in 1.8

有谁知道这是 1.8 中的一个错误,恰好在 1.9 中修复,或者可能是在 1.9 中有意改变的预期行为?我尝试在其他地方找到有关此问题的提及或文档,但找不到任何东西。

由于这个问题,有谁知道检查单例类是否是ARuby 1.8 中的子类的最佳方法是什么?我一直在做(class << b; self; end).ancestors.include?(A)一种解决方法,尽管它在技术上并不“正确”,因为祖先列表也包含包含的模块。

4

1 回答 1

1

我会建议:

class Object; def metaclass; class << self; self; end; end; end

class A; end
class B < A; end

b = B.new

b.metaclass < A.metaclass || b.metaclass < A

在 Ruby 1.8、1.9 和 2.0 中测试。

于 2013-03-11T22:36:11.633 回答