Ruby 中 BasicObject 的单例类的单例类

Posted

技术标签:

【中文标题】Ruby 中 BasicObject 的单例类的单例类【英文标题】:Singleton class of singleton class of BasicObject in Ruby 【发布时间】:2018-12-10 11:00:17 【问题描述】:

这主要是一个“学术”,但在这里:

根据这个 Ruby 特征类图(稍作编辑):

BasicObject.singleton_class.singleton_class.superclassClass

但是,在 Ruby 解释器 (Ruby v2.5.1) 上运行它,结果发现 BasicObject.singleton_class.singleton_class.superclass#<Class:Class> 而不是 Class。因此,图表是在说谎还是我遗漏了什么?

该图来自我在 Freenode 的 Ruby IRC 聊天的一位用户。然而,它被许多其他用户多次引用,并被视为 Ruby 对象模型圣经。

【问题讨论】:

BasicObject.singleton_class.singleton_class.is_a?(Class) #⇒ true #Class 是一个字符串表示形式。 你的问题是BasicObject.singleton_class.singleton_class,但你的图表是BasicObject.singleton_class.singleton_class.superclass。请澄清。 @kstratis:啊,我明白了。好吧,当图表与现实发生冲突时,“哪个是正确的”的答案是显而易见的。 :) 你一直说#Class。你看到这个的 ruby​​ 版本和/或环境是什么?对我来说是#<Class:Class> 检查了几个 ruby​​ 版本到 1.9.3。都表现出相同的行为。猜猜我们一直在读错误的圣经:) 【参考方案1】:

Ruby 解释器的行为非常合理,因为:

Child 类扩展Parent 时,Ruby 设置它以便单例类#<Class:Child> 也扩展#<Class:Parent>;和 BasicObject.singleton_classClass 的子类,所以BasicObject.singleton_class.singleton_class 将是#<Class:Class> 的子类

验证相等性:

BasicObject.singleton_class.singleton_class.superclass.equal?(Class.singleton_class)
#=> true

这就引出了下一个问题——为什么#<Class:BaseObject>首先要扩展Class?按照上面的规则,由于BaseObject 没有超类——也就是说,BaseObject.superclassnil——合乎逻辑的事情是它的单例类也没有超类。

答案是#<Class:BaseObject> 扩展Class 确保在涉及单例类时继承层次结构的一致性。以这个 Ruby 对象为例:

obj = "a string"

我们可以将obj 视为String 的一个(唯一)实例,而不是obj 987654340@。那就是:

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,通过沿着继承链向上走,它最终还是会到达那里......

【讨论】:

以上是关于Ruby 中 BasicObject 的单例类的单例类的主要内容,如果未能解决你的问题,请参考以下文章

Ruby中的类和该类的单例有啥区别?

更改对不同类加载器加载的单例类的影响

如何创建一个完美的单例模式

一篇文章带你搞清Ruby对象模型

我去,这才是完美的单例模式!

单例类和元类