这主要是一个“学术”的,但它是这样的:
根据这个 Ruby 特征类图(略有编辑):
BasicObject.singleton_class.singleton_class.superclass
是Class
.
但是,在 Ruby 解释器 (Ruby v2.5.1) 上运行它,结果是 BasicObject.singleton_class.singleton_class.superclass
是#<Class:Class>
而不是 Class
.因此,图表是在撒谎还是我遗漏了什么?
该图来 self 在 Freenode 的 Ruby IRC 上与一位用户聊天。但是,它已被许多其他用户多次引用,并被视为 Ruby 对象模型圣经。
最佳答案
Ruby 解释器的行为非常合理,因为:
- 当
Child
类扩展了一个Parent
, 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
没有父类(super class)——即BaseObject.superclass
是nil
– 合乎逻辑的是它的单例类也没有父类(super class)。
答案是#<Class:BaseObject>
扩展 Class
当涉及到单例类时,确保继承层次结构的一致性。以这个 Ruby 对象为例:
obj = "a string"
这是一个公认的概念,而不是 obj
只是 String
的一个实例,我们可以将其视为它自己的单例类的(唯一)实例,而单例类又是 String
的子类。 .即:
obj.class.equal?(obj.singleton_class.superclass)
#=> true
同样适用于类实例似乎是合乎逻辑的。但事实并非如此,因为它与上面提到的规则相矛盾,其中 Child
的单例类的父类(super class)class 是其 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
,通过沿着继承链向上走,它最终确实到达了那里......
关于ruby - Ruby中BasicObject单例类的单例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51132394/