Ruby eigenclass意外行为

baz*_*tas 4 ruby metaprogramming eigenclass

首先,让我们添加一个方法来检索"从此博客帖子中复制"的特征类

class Object 
  def eigenclass 
    class << self
      self
    end 
  end 
end
Run Code Online (Sandbox Code Playgroud)

然后创建一个简单的类

class A
end

puts A.new.eigenclass.superclass      # => A
puts Class.new.eigenclass.superclass  # => #<Class:Object>
Run Code Online (Sandbox Code Playgroud)

我期待第二次投入输出Class

任何线索为什么会这样?

kid*_*ils 5

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

背景故事:

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

因此obj = Foo.new,类层次结构实际上看起来像:

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

代替:

obj - (类) - > A.

在你用自己劫持自己之后,可以产生一个隐藏的类#eigenclass.

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

A - (本征类) - ># - (超类) - >#

现在它之所以显示#而不是A因为Ruby以非常漂亮的模式组织了类,超类和特征类.这可以用示例显示,而不是用令人困惑的词语引用它:

A.superclass #=> Object   
A.eigenclass #=> #<Class: A>   
A.eigenclass.superclass #=> #<Class: Object> => Eigenclass of Object   
A.eigenclass.superclass == Object.eigenclass #=> true   
Run Code Online (Sandbox Code Playgroud)

一个eigenclass的超一的是原始的超类的eigenclass .

现在,来看你的情况:Class.new.eigenclass.superclass现在这是不言自明的.Class.new对应一个新的匿名类,比如说B,你正在有效地调用eigenclass.superclass它.由于超类B是Object,B的本征类的超类是超类的特征类B.

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

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

问候