kst*_*tis 5 ruby metaprogramming eigenclass
这主要是一个"学术"的,但在这里:
根据这个Ruby eigenclass图(略加编辑):
BasicObject.singleton_class.singleton_class.superclass是Class.
但是,在Ruby解释器(Ruby v2.5.1)上运行它,事实证明它BasicObject.singleton_class.singleton_class.superclass是#<Class:Class>和不是Class.因此,图表是说谎还是我遗漏了什么?
该图来自我在Freenode的Ruby IRC聊天的用户.但是,它被多次引用给许多其他用户,它被视为Ruby对象模型圣经.
Ruby 解释器的行为非常有意义,因为:
Child类扩展 a时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
Run Code Online (Sandbox Code Playgroud)
这就引出了下一个问题——为什么要#<Class:BaseObject>扩展Class?遵循上述规则,sinceBaseObject没有超类——也就是说,BaseObject.superclass它nil的单例类也没有超类,这是合乎逻辑的。
答案是,当涉及到单例类时,#<Class:BaseObject>扩展可确保继承层次结构的一致性。Class以这个 Ruby 对象为例:
obj = "a string"
Run Code Online (Sandbox Code Playgroud)
这是一个公认的概念,我们可以将其视为其自己的单例类的(唯一)实例,而不是obj简单地作为String的实例,而单例类又是 的子类String。那是:
obj.class.equal?(obj.singleton_class.superclass)
#=> true
Run Code Online (Sandbox Code Playgroud)
这似乎也适用于类实例,这似乎是合乎逻辑的。但事实并非如此,因为它与上面提到的规则相矛盾,其中一个类的单例类的超类Child是其类的单例类Parent。
class Foo; end
Foo.class
#=> Class
Foo.singleton_class.superclass
#=> #<Class:Object> <-- not equal to Class!
# because:
Foo.superclass
#=> Object
Run Code Online (Sandbox Code Playgroud)
但是可以通过放置Class在单例类继承层次结构的顶部来解决这个矛盾:
Foo.singleton_class.superclass
#=> #<Class:Object>
Foo.singleton_class.superclass.superclass
#=> #<Class:BasicObject>
Foo.singleton_class.superclass.superclass.superclass
#=> Class
Run Code Online (Sandbox Code Playgroud)
这样,即使Foo.singleton_class.superclass不等于Foo.class,通过沿着继承链向上走,它最终还是会到达那里......
| 归档时间: |
|
| 查看次数: |
253 次 |
| 最近记录: |