Ruby 中 Base 类和 Derived 类的元类之间有什么关系?
在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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里有四个类对象在起作用:
命名法:
当您调用 Derived.class_method 时,Ruby 遵循“右一后向上”规则:首先转到对象的类,然后沿着超类链向上,找到方法时停止:
Derived 没有定义该方法,因此 Ruby 沿着链向上到达 #Derived 的超类,即 #Base。
您认为我不可能立即知道所有这些内容,是吗?这就是我的大脑获得所有这些元juju的地方:元编程Ruby。
第 2 部分。 如何使“特征类”(又名“单例类”)不再隐藏。
此方法将返回任何对象的特征类。现在,课程怎么样?这些也是物体。
注:以上来自Ruby1.9。当在 Ruby 1.8 下运行时,你会得到一个惊喜:
There are four class objects in play here:
Nomenclature:
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 does not define the method, so Ruby follows the chain up the chain to #Derived's superclass, which is #Base.
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
This method will return the eigenclass of any object. Now, what about classes? Those are objects, too.
Note: Above is from Ruby1.9. When run under Ruby 1.8, you get a surprise:
为了澄清和纠正我在评论中写的有关 Ruby 隐藏/公开特征类的方式的内容,情况如下:
Ruby 1.8:
(1)
Object#class
方法始终返回第一个实数(非特征类)或 iclass)对象的实际类的超类。换句话说
,
Object#class
方法永远不会返回特征类,它会传递它们而是返回它在继承层次结构中找到的第一个“真实”类。
(2)
Class#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 方法不再有两种情况,它现在像对待普通类一样对待特征类,并按预期返回实际的超类。
例如
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
In other words, the
Object#class
method will never return an eigenclass, it passes over themand 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.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
下图解释了这种关系: 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/