在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
但是,我似乎并不了解super
中对Derived.class_method
的调用是如何达到Base.class_method
的。我假设class_method
是在他们的元类上定义的,这是否意味着他们的元类有父/子关系? (我无法通过实验证实)
更新:我问的是这个问题,因为我记得看到某个地方在基础和派生类'元类之间存在某种关系(但我找不到它)更多)。除了知道实际super
如何工作之外,我还想确认两个元类是否完全分开。
答案 0 :(得分:11)
这里有四个类对象:
<Class>---class---><Class>
Base #Base
^ ^
| |
| |
super super
| |
| |
<Class> <Class>
Derived---class--->#Derived
命名法:
当您调用Derived.class_method时,Ruby遵循“正确的一个然后向上”规则:首先转到对象的类,然后按照超类链,在找到方法时停止:
你认为我不知道所有这些东西是不是我的头脑,是吗?在这里,我的大脑得到了所有这些元juju:Metaprogramming 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>
答案 1 :(得分:4)
为了澄清和纠正我在关于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
在正常类的情况下表现如预期,但对于本征类示例,它表明Module的本征类的超类是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
方法不再有两种情况,它现在以与处理普通类相同的方式处理本征类,并按预期返回实际的超类。
e.g
class << Module; superclass; end #=> #<Class:Object>
答案 2 :(得分:3)
此图解释了关系: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/the-secret-life-of-singletons/