简体   繁体   English

Ruby eigenclass意外行为

[英]Ruby eigenclass unexpected behaviour

First, let's add a method to retrieve eigenclass "copied from this blog post " 首先,让我们添加一个方法来检索“从此博客帖子中复制”的特征类

class Object 
  def eigenclass 
    class << self
      self
    end 
  end 
end

Then create a simple class 然后创建一个简单的类

class A
end

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

I was expecting the second puts to output Class 我期待第二次投入输出Class

Any clue why this happened? 任何线索为什么会这样?

By puts A.new.eigenclass.superclass , you are effectively calling #eigenclass on the instance of class A. I will begin with backstory to explain how eigenclass actually works, and will then proceed to tell what is happening in your code. 通过puts A.new.eigenclass.superclass ,您#eigenclass在类A的实例上调用#eigenclass 。我将从后台开始解释eigenclass实际上是如何工作的,然后将继续告诉代码中发生了什么。

BackStory: 背景故事:

EigenClass is a hidden class which contains the singleton methods available for that specific object only. EigenClass是一个隐藏类,它包含仅适用于该特定对象的单例方法。

So for obj = Foo.new , the class hierarchy actually looks like: 所以对于obj = Foo.new ,类层次结构实际上看起来像:

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

instead of: 代替:

obj --(class)--> A obj - (类) - > A.

A hidden class can be produced after you hijacked the self with #eigenclass . 使用#eigenclass劫持自我后,可以生成隐藏的类。

Now, in Ruby, Class is an object. 现在,在Ruby中, Class是一个对象。 This also means that #eigenclass should show the the hidden eigenclass of A too (where A's sigleton methods are kept). 这也意味着#eigenclass应该显示A的隐藏本征类(其中保留了A的sigleton方法)。

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

Now the reason why it shows # instead of A is because Ruby organizes the classes, superclasses and eigenclasses in a very beautiful pattern. 现在它之所以显示而不是A是因为Ruby以非常漂亮的模式组织了类,超类和特征类。 This can be shown with example instead of quoting it in confusing words: 这可以用示例显示,而不是用令人困惑的词语引用它:

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

The superclass of an eigenclass of a class is the eigenclass of the superclass of the original class . 类的本征 的超类是原始的超类的本征

Now, coming to your case: Class.new.eigenclass.superclass , this is self-explanatory now. 现在, Class.new.eigenclass.superclass你的情况: Class.new.eigenclass.superclass ,现在这是不言自明的。 Class.new corresponds to a new anonymous class, say B , and you are effectively calling eigenclass.superclass on it. Class.new对应一个新的匿名类,比如B ,你实际上是在调用eigenclass.superclass Since the superclass of B is Object, the superclass of eigenclass of B is the eigenclass of superclass of B . 由于B的超类是Object,B的本征类的超类是B的超类的本征类。

Tried my best to explain with examples. 我尽力用例子来解释。 Please feel free to clarify it further in comments below; 请在下面的评论中进一步澄清; will update the answer accordingly. 将相应更新答案。 Complementary(from Pragmatic MR): 补充(来自Pragmatic MR): 从语用MR中拍摄 .

In the figure shown above, D inherits from C . 在上图中, D继承自C So D.eigenclass.superclass is the eigneclass of (superclass of D)[which is C]. 所以D.eigenclass.superclass是(D的超类)[它是C]的eigneclass。 Now C's superclass is Object.. and so is the same logic. 现在C的超类是Object ..所以是相同的逻辑。

Regards 问候

From that blogpost, you can construct a similar diagram: 从该博文中,您可以构建一个类似的图表:

                        +------------------+               +-------------------+
                        |      Object      |- eigenclass ->| Object eigenclass |
                        +------------------+               +-------------------+
                                 ^                                   ^             
                                 | superclass             superclass |                                                     
                        +------------------+               +-------------------+
                        |        A         |- eigenclass ->|    A eigenclass   |
                        +------------------+               +-------------------+
                                 ^
                                 | superclass
+-------+               +------------------+                                   
| A.new |- eigenclass ->| A.new.eigenclass |                                   
+-------+               +------------------+    

Trying to find the superclass of the eigenclass of an instance of A shows that it points to the A class. 试图找到A实例的本征类的超类表明它指向A类。

A.new.eigenclass.superclass      # => A                               

Class.new returns an instance of a Class object, ie a new class. Class.new返回Class对象的实例,即一个新类。 It is a class, just like the A class. 这是一个类,就像A类一样。

Class.new.class # => Class
A.class         # => Class

A's superclass and Class.new's superclass are both implicitly Object . A的超类和Class.new的超类都是隐式的Object

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

Because A's superclass is Object , A's eigenclass's superclass is Object's eigenclass. 因为A的超类是Object ,A的本征类的超类是Object的特征类。

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

Similarly, finding the superclass of the eigenclass of Class.new yields Object's eigenclass 同样的,找到的eigenclass的超Class.new产生对象的eigenclass

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

The difference between Class.new and A.new is that Class.new is itself a class and so can construct new objects, while A.new cannot. 之间的区别Class.newA.newClass.new本身就是一类,因此可以构建新的对象,而A.new不能。

Class.new.new # => #<#<Class:0x007f86b50d8f70>:0x007f86b50d8f20>
A.new.new     # => NoMethodError: undefined method `new' for #<A:0x007f86b50cbf50>

A class's eigenclass has a whole shadow hierarchy of eigenclasses for the class's ancestors that all go between the eigenclass and Class. 类的本征类具有整个类的本体类的阴影层次,用于类的祖先,它们都在本征类和类之间。 This is because classes are expected to inherit their ancestors' class methods. 这是因为期望类继承其祖先的类方法。 For example, if you did def Numeric.kind_of_number?() true end , you would expect Fixnum.kind_of_number? 例如,如果你确定def Numeric.kind_of_number?() true end ,你会期望Fixnum.kind_of_number? to be true. 是真实的。 So you need to have Numeric's eigenclass as an ancestor of Fixnum's eigenclass. 所以你需要将Numeric的本征类作为Fixnum的本征类的祖先。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM