4

首先,让我们添加一个方法来检索“从这篇博文复制”的 eigenclass

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>

我期待第二个输出

任何线索为什么会这样?

4

3 回答 3

5

通过puts A.new.eigenclass.superclass,您实际上是在调用A 类#eigenclass实例。我将从背景故事开始解释 eigenclass 的实际工作原理,然后继续讲述您的代码中发生了什么。

背景故事:

EigenClass是一个隐藏类,其中包含仅适用于该特定对象的单例方法。

所以对于obj = Foo.new,类层次结构实际上看起来像:

obj --eigenclass--> #> --(超类)--> A

代替:

obj --(class)--> A

用劫持self后可以产生一个隐藏类#eigenclass

现在,在 Ruby 中,Class是一个对象。这也意味着#eigenclass应该显示也隐藏的特征类A(保留 A 的 sigleton 方法的地方)。

A --(eigenclass)--> # --(超类)--> #

现在之所以显示#而不是,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对应于一个新的匿名类,say B,并且您正在有效地调用eigenclass.superclass它。由于 的超类B是 Object,所以 B 的 eigenclass 的超类是 的超类的 eigenclass B

尽我所能用例子来解释。请随时在下面的评论中进一步澄清;将相应地更新答案。补充(来自 Pragmatic MR)从 Pragmatic MR 拍摄:。

在上图中,D继承自C. D.eigenclass.superclass(D 的超类)[即 C] 的 eigneclass 也是如此。现在 C 的超类是 Object.. 也是同样的逻辑。

问候

于 2014-06-04T00:03:50.643 回答
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 的超类和 Class.new 的超类都是隐式的Object

Class.new.superclass # => Object
A.superclass         # => Object

因为 A 的超类是Object,所以 A 的 eigenclass 的超类是 Object 的 eigenclass。

Object.eigenclass                            # => #<Class:Object>
A.eigenclass.superclass                      # => #<Class:Object>
A.eigenclass.superclass == Object.eigenclass # => true

类似地,找到 的 eigenclass 的超类Class.new产生 Object 的 eigenclass

Class.new.eigenclass.superclass              # => #<Class:Object>

Class.new和之间的区别在于A.newClass.new本身是一个类,因此可以构造新对象,而A.new不能。

Class.new.new # => #<#<Class:0x007f86b50d8f70>:0x007f86b50d8f20>
A.new.new     # => NoMethodError: undefined method `new' for #<A:0x007f86b50cbf50>
于 2014-06-04T00:11:46.537 回答
1

一个类的 eigenclass 具有整个 eigenclasses 的影子层次结构,用于该类的祖先,它们都位于 eigenclass 和 Class 之间。这是因为类应该继承其祖先的类方法。例如,如果你这样做了def Numeric.kind_of_number?() true end,你会期望Fixnum.kind_of_number?是真的。因此,您需要将 Numeric 的 eigenclass 作为 Fixnum 的 eigenclass 的祖先。

于 2014-06-03T22:39:09.363 回答