首先,让我们添加一个方法来检索“从this blog post复制的本征类”
class Object
def eigenclass
class << self
self
end
end
end
然后创建一个简单的类
class A
end
puts A.new.eigenclass.superclass # => A
puts Class.new.eigenclass.superclass # => #<Class:Object>
我期待第二次投放 Class
有什么理由发生这种情况?
答案 0 :(得分:5)
通过puts A.new.eigenclass.superclass
,您实际上是在A类的实例上调用#eigenclass
。我将从背景故事开始解释eigenclass实际上是如何工作的,然后将继续告诉您代码中发生了什么。
<强>背景故事:强>
EigenClass 是一个隐藏类,其中包含仅适用于该特定对象的单例方法。
因此,对于obj = Foo.new
,类层次结构实际上如下所示:
obj --eigenclass - &gt; #&GT; - (超) - &GT;甲
而不是:
obj - (类) - &gt;甲
使用#eigenclass
劫持自我后,可以生成隐藏的类。
现在,在Ruby中,类是一个对象。这也意味着#eigenclass
也应该显示隐藏的本征类A
(其中保留了A的sigleton方法)。
A - (本征类) - &gt; # - (超类) - &gt; #
现在它显示#而不是A
的原因是因为Ruby以非常漂亮的模式组织了类,超类和特征类。这可以用示例显示,而不是用令人困惑的词语引用它:
A.superclass #=> Object
A.eigenclass #=> #<Class: A>
A.eigenclass.superclass #=> #<Class: Object> => Eigenclass of Object
A.eigenclass.superclass == Object.eigenclass #=> true
类的特征类的超类是原始类的超类的本征类。
现在,来看你的案例:Class.new.eigenclass.superclass
,现在这是不言自明的。 Class.new
对应一个新的匿名类,比如B
,您实际上正在调用eigenclass.superclass
。由于B
的超类是Object,因此B的本征类的超类是B
的超类的本征类。
尽我所能用例子解释。请在下面的评论中进一步澄清;将相应更新答案。补充(来自Pragmatic MR):。
在上图中,D
继承自C
。所以D.eigenclass.superclass
是(D的超类)[即C]的eigneclass。现在C的超类是Object ..所以逻辑也一样。
此致
答案 1 :(得分:4)
从该博文中,您可以构建一个类似的图表:
+------------------+ +-------------------+
| Object |- eigenclass ->| Object eigenclass |
+------------------+ +-------------------+
^ ^
| superclass superclass |
+------------------+ +-------------------+
| A |- eigenclass ->| A eigenclass |
+------------------+ +-------------------+
^
| superclass
+-------+ +------------------+
| A.new |- eigenclass ->| A.new.eigenclass |
+-------+ +------------------+
试图找到A实例的特征类的超类,表明它指向A
类。
A.new.eigenclass.superclass # => A
Class.new
返回Class对象的实例,即新类。这是一个类,就像A
类一样。
Class.new.class # => Class
A.class # => Class
A&#39的超类和Class.new的超类都隐含Object
。
Class.new.superclass # => Object
A.superclass # => Object
因为A的超类是Object
,所以A&#39的超类是对象的特征类。
Object.eigenclass # => #<Class:Object>
A.eigenclass.superclass # => #<Class:Object>
A.eigenclass.superclass == Object.eigenclass # => true
类似地,找到Class.new
的本征类的超类产生对象的本征类
Class.new.eigenclass.superclass # => #<Class:Object>
Class.new
和A.new
之间的区别在于Class.new
本身就是一个类,因此可以构建新对象,而A.new
则不能。
Class.new.new # => #<#<Class:0x007f86b50d8f70>:0x007f86b50d8f20>
A.new.new # => NoMethodError: undefined method `new' for #<A:0x007f86b50cbf50>
答案 2 :(得分:1)
一个类的本征类对于类的祖先有一个完整的特征类阴影层次结构,它们都在本征类和类之间。这是因为期望类继承其祖先的类方法。例如,如果您执行了def Numeric.kind_of_number?() true end
,则您希望Fixnum.kind_of_number?
为真。所以你需要将Numeric的本征类作为Fixnum的本征类的祖先。