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

发布于 2024-08-19 08:14:56 字数 643 浏览 7 评论 0原文

在Ruby中,我们可以在单例方法中使用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

但是,我似乎不太明白 Derived.class_method 中对 super 的调用如何到达 Base.class_method。我假设 class_method 是在他们的元类上定义的,这是否意味着他们的元类具有父/子关系? (我无法通过实验完全证实这一点)

更新:我问这个问题是因为我记得在某个地方看到基类和派生类的元类之间存在某种关系(但我再也找不到了)。除了了解 super 实际上是如何工作的之外,我还想确认这两个元类是否完全独立。

In Ruby, we could use super within singleton method to call the corresponding super class's singleton method, like the following code shows.

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. I'd assume that class_method is defined on their metaclass, does that mean their metaclass has parent/child relationship? (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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风吹雨成花 2024-08-26 08:14:56

这里有四个类对象在起作用:

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

命名法:

  • <...>是每个对象的类。
  • 类的名称位于第二行。
  • 如果名称以 # 开头,则它是特征类(又名单例类)。
  • super 指向类的超类
  • class 指向该类的类。

当您调用 Derived.class_method 时,Ruby 遵循“右一后向上”规则:首先转到对象的类,然后沿着超类链向上,找到方法时停止:

  • “class_method”调用的接收者是 Derived 。因此,沿着链一直到 Derived 的类对象,这是它的特征类 (#Derived)。
  • Derived 没有定义该方法,因此 Ruby 沿着链向上到达 #Derived 的超类,即 #Base。

  • 在那里找到了该方法,因此 Ruby 将消息分派到 #Base.class_method

您认为我不可能立即知道所有这些内容,是吗?这就是我的大脑获得所有这些元juju的地方:元编程Ruby

第 2 部分。 如何使“特征类”(又名“单例类”)不再隐藏。

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

此方法将返回任何对象的特征类。现在,课程怎么样?这些也是物体。

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

注:以上来自Ruby1.9。当在 Ruby 1.8 下运行时,你会得到一个惊喜:

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

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.

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:

  • The receiver of the "class_method" call is Derived. So follow the chain right to Derived's class object, which is its eigenclass (#Derived).
  • Derived does not define the method, so Ruby follows the chain up the chain to #Derived's superclass, which is #Base.

  • The method is found there, so Ruby dispatches the message to #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.

Part 2. How to make an "eigenclass" (aka "singleton class") come out of hiding

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. When run under Ruby 1.8, you get a surprise:

p Derived.eigenclass.superclass    # => #<Class:Class>
春庭雪 2024-08-26 08:14:56

为了澄清和纠正我在评论中写的有关 Ruby 隐藏/公开特征类的方式的内容,情况如下:

Ruby 1.8:

(1) Object#class 方法始终返回第一个实数(非特征类)或 iclass)对象的实际类的超类。
换句话说

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

Object#class 方法永远不会返回特征类,它会传递它们
而是返回它在继承层次结构中找到的第一个“真实”类。

(2)Class#superclass方法有两种情况。如果接收者不是特征类,那么它只是返回超类。但是,如果接收者是一个特征类,则此方法返回接收者的实际(即不一定是真实的)类。

# 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

从上面来看,Class#superclass 在普通类的情况下表现得与预期相同,但对于 eigenclass 示例,它声明 Module eigenclass 的超类是 Class,但事实并非如此。从该图中http://banisterfiend.wordpress。 com/2008/10/25/the-secret-life-of-singletons/我们知道Module的特征类的超类实际上是Object的特征类。我不确定为什么 Ruby 1.8 有这种奇怪的行为。

Ruby 1.9:

(1) Object#class 方法的行为与 1.8 版本相同。

(2) Class#superclass 方法不再有两种情况,它现在像对待普通类一样对待特征类,并按预期返回实际的超类。

例如

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

To clarify and correct what i wrote in the comments regarding the way Ruby hides/exposes eigenclasses, here is the situation:

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.
e.g

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.

(2) The Class#superclass method has two cases. 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 (i.e 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. 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. I am unsure why Ruby 1.8 has this strange behaviour.

Ruby 1.9:

(1) The Object#class method behaves identically to the 1.8 version.

(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.

e.g

class << Module; superclass; end #=> #<Class:Object>
素年丶 2024-08-26 08:14:56

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

另外,这里还有一些其他帖子更多地解释了特征类的复杂性:
http://www.klankboomklang.com/2007/10/05/the -metaclass/

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

这是一个相当困难的例子,它解释的内容比您可能想知道的更多:
http://banisterfiend.wordpress.com/2008 /10/25/单身人士的秘密生活/

This diagram explains the relationship: 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/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/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文