简体   繁体   English

Ruby中元类的Base和Derived类之间的关系是什么?

[英]What is the relationship between the metaclass of Base and Derived class in Ruby?

In Ruby, we could use super within singleton method to call the corresponding super class's singleton method, like the following code shows. 在Ruby中,我们可以在singleton方法中使用super来调用相应的超类的单例方法,如下面的代码所示。

class Base
  def self.class_method
    puts "Base class method"
  end
end

class Derived < Base
  def self.class_method
    puts "Derived class method"
    super
  end
end

Derived.class_method
# Derived class method
# Base class method

However, I don't seem quite get how that call to super within Derived.class_method could reach Base.class_method . 但是,我似乎并不完全了解Derived.class_methodsuper调用是如何达到Base.class_method I'd assume that class_method is defined on their metaclass, does that mean their metaclass has parent/child relationship? 我假设class_method是在他们的元类上定义的,这是否意味着他们的元类有父/子关系? (I can't quite confirm that by experiments) (我无法通过实验确认)

Update : I'm asking this question because I remembered seeing somewhere there's some kind of relationship bettwen base and derived class' metaclass (but I can't find it any more). 更新 :我问的是这个问题,因为我记得在某个地方看到基地和派生类'元类之间存在某种关系(但我再也找不到了)。 In addition to know how actually super works, I'd also like to confirm whether the two metaclasses are totally separate or not. 除了知道实际super如何工作之外,我还想确认两个元类是否完全分开。

There are four class objects in play here: 这里有四个类对象:

<Class>---class---><Class>
Base               #Base
   ^                  ^
   |                  |
   |                  |
 super              super
   |                  |
   |                  |
<Class>            <Class>
Derived---class--->#Derived

Nomenclature: 命名:

  • <...> is the class of each object. <...>是每个对象的类。
  • The name of the class is on the second line. 该类的名称位于第二行。
  • If the name starts with #, it's the eigenclass (aka singleton class). 如果名称以#开头,则它是本征类(也称为单例类)。
  • super points to a class's superclass 超级指向一个班级的超类
  • class points to the class's class. class指向类的类。

When you call Derived.class_method, Ruby follows the "right one and then up" rule: First go to the object's class, then follow the superclass chain up, stopping when the method is found: 当您调用Derived.class_method时,Ruby遵循“正确的一个然后向上”规则:首先转到对象的类,然后按照超类链,在找到方法时停止:

  • The receiver of the "class_method" call is Derived. “class_method”调用的接收者是Derived。 So follow the chain right to Derived's class object, which is its eigenclass (#Derived). 因此,请遵循链接到Derived的类对象,这是它的特征类(#Derived)。
  • Derived does not define the method, so Ruby follows the chain up the chain to #Derived's superclass, which is #Base. Derived没有定义方法,所以Ruby跟链链接到#Derived的超类,即#Base。

  • The method is found there, so Ruby dispatches the message to #Base.class_method 在那里找到了该方法,因此Ruby将消息分派给#Base.class_method

You don't think I knew all this stuff off the top of my head, did you? 你不觉得我知道所有这些东西都是我的头脑,是吗? Here's where my brain got all this meta juju: Metaprogramming Ruby . 在这里,我的大脑得到了所有这些元juju: Metaprogramming Ruby

Part 2. How to make an "eigenclass" (aka "singleton class") come out of hiding 第2部分。如何使“本征类”(又名“单身类”)脱离隐藏

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

This method will return the eigenclass of any object. 此方法将返回任何对象的本征类。 Now, what about classes? 现在,课程怎么样? Those are objects, too. 那些也是对象。

p Derived.eigenclass               # => #<Class:Derived>
p Derived.eigenclass.superclass    # => #<Class:Base>
p Base.eigenclass                  # => #<Class:Base>

Note: Above is from Ruby1.9. 注意:上面是Ruby1.9。 When run under Ruby 1.8, you get a surprise: 在Ruby 1.8下运行时,你会感到惊讶:

p Derived.eigenclass.superclass    # => #<Class:Class>

To clarify and correct what i wrote in the comments regarding the way Ruby hides/exposes eigenclasses, here is the situation: 为了澄清和纠正我在关于Ruby隐藏/暴露本征类的方式的评论中所写的内容,情况如下:

Ruby 1.8: Ruby 1.8:

(1) The Object#class method always returns the first real (non eigenclass or iclass) superclass of the actual class of an object. (1) Object#class方法总是返回对象实际类的第一个真实(非本征类或iclass)超类。 eg 例如

o = Object.new
class << o; end
o.class #=> returns Object, even though the _actual_ class is the eigenclass of o

In other words, the Object#class method will never return an eigenclass, it passes over them and instead returns the first 'real' class it finds in the inheritance hierarchy. 换句话说, Object#class方法永远不会返回特征类,它会遍历它们,而是返回它在继承层次结构中找到的第一个“真实”类。

(2) The Class#superclass method has two cases. (2) Class#superclass方法有两种情况。 If the receiver is not an eigenclass then it simply returns the superclass. 如果接收者不是本征类,那么它只返回超类。 However, if the receiver is an eigenclass then this method returns the actual (ie not necessarily real) class of the receiver. 但是,如果接收器本征类,则该方法返回接收器的实际 (即不一定是真实的)类。

# case where receiver is a normal class (i.e not an eigenclass)
Module.superclass #=> Object (behaves as expected)

# case where receiver is an eigenclass
class << Module; superclass; end #=> returns Class, this is NOT the superclass

From above, Class#superclass behaves as expected in the case of a normal class, but for the eigenclass example it states the superclass of the eigenclass of Module is Class which is not true. 从上面看, Class#superclass在普通类的情况下表现如预期,但对于本征类示例,它表明Module的本征类的超类是Class,而不是真的。 From this diagram http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/ we know that the superclass of the eigenclass of Module is actually the eigenclass of Object. 从这个图http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/我们知道Module的本征类的超类实际上是Object的本征类。 I am unsure why Ruby 1.8 has this strange behaviour. 我不确定为什么Ruby 1.8有这种奇怪的行为。

Ruby 1.9: Ruby 1.9:

(1) The Object#class method behaves identically to the 1.8 version. (1) Object#class方法的行为与1.8版本相同。

(2) The Class#superclass method no longer has two cases, it now treats eigenclasses the same way it treats normal classes and returns the actual superclass as expected. (2) Class#superclass方法不再有两种情况,它现在以与处理普通类相同的方式处理本征类,并按预期返回实际的超类。

eg 例如

class << Module; superclass; end #=> #<Class:Object>

This diagram explains the relationship: http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/ 该图解释了这种关系: http//banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

Also, here are some other posts that explain more the intricacies of eigenclasses: http://www.klankboomklang.com/2007/10/05/the-metaclass/ 此外,这里有一些其他帖子解释了更多本征类的复杂性: http ://www.klankboomklang.com/2007/10/05/the-metaclass/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/ http://www.klankboomklang.com/2007/09/21/the-singleton-class/

And here's a fairly hard-going one that explains more than you'd probably like to know: http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/ 这里有一个相当难以理解的解释超过你可能想知道的更多: http//banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

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

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