Ruby 解释器的行为非常合理,因为:
- 当一个
Child
类扩展 aParent
时,Ruby 设置它以便单例类也#<Class:Child>
扩展#<Class:Parent>
;和
BasicObject.singleton_class
是 的子类Class
,所以BasicObject.singleton_class.singleton_class
将是 的子类#<Class:Class>
验证相等性:
BasicObject.singleton_class.singleton_class.superclass.equal?(Class.singleton_class)
#=> true
这就引出了下一个问题——为什么首先要#<Class:BaseObject>
扩展Class
?按照上面的规则,因为BaseObject
没有超类——也就是说,BaseObject.superclass
是nil
——合乎逻辑的事情是它的单例类也没有超类。
答案是,当涉及到单例类时,#<Class:BaseObject>
扩展确保了继承层次结构的一致性。Class
以这个 Ruby 对象为例:
obj = "a string"
这是一个公认的概念,我们可以将其视为其自己的单例类的(唯一)实例,而不是obj
简单的实例,而单例类又是 的子类。那是:String
String
obj.class.equal?(obj.singleton_class.superclass)
#=> true
这似乎也适用于类实例是合乎逻辑的。但它没有,因为它与上面提到的规则相矛盾,其中一个类的单例类的超Child
类是其类的单例Parent
类。
class Foo; end
Foo.class
#=> Class
Foo.singleton_class.superclass
#=> #<Class:Object> <-- not equal to Class!
# because:
Foo.superclass
#=> Object
但是可以通过放置Class
在单例类继承层次结构的顶部来解决这个矛盾:
Foo.singleton_class.superclass
#=> #<Class:Object>
Foo.singleton_class.superclass.superclass
#=> #<Class:BasicObject>
Foo.singleton_class.superclass.superclass.superclass
#=> Class
这样,即使Foo.singleton_class.superclass
不等于Foo.class
,通过沿着继承链向上走,它最终也会到达那里......