为什么这样设计?
Ruby的设计倾向于尽可能多地实现方法;关键字通常保留用于具有自己的语法规则的语言功能。但是,super
的外观和行为类似于方法调用。
(我知道在纯Ruby中实现super
会很麻烦,因为它必须从caller
或use a trace_func解析方法名称。防止它成为一个方法,因为大量的Kernel方法没有在纯Ruby中实现。)
答案 0 :(得分:5)
它的行为有点不同,因为如果你不传递参数,所有当前的参数(和块,如果存在的话)都会被传递......我不确定它将如何作为一种方法。
给出一个相当人为的例子:
class A
def example(a, b, c)
yield whatever(a, b) + c
end
end
class B < A
def example(a, b, c)
super * 2
end
end
我不需要处理yield,也不需要将参数传递给super
。在您特别想要传递不同参数的情况下,它的行为更像是方法调用。如果您想完全不传递参数,则必须传递空括号(super()
)。
它与方法调用的行为完全不同。
答案 1 :(得分:1)
super
不会自动调用父类的方法。如果您将ruby类的继承层次结构想象为列表,底部的类和顶部的Object
,当ruby看到super
关键字时,而不是仅检查父类,它会向上移动整个列表,直到找到第一个具有使用该名称定义的方法的项目。
我小心说项目,因为它也可能是模块。当你将一个模块包含在一个类中时,它被包装在一个匿名的超类中,并放在我之前讨论的列表中的类之上,这意味着如果你有一个为你的类定义的方法,也是在模块中定义的,然后从类的实现中调用super将调用模块的实现,而不是父类的:
class Foo
def f
puts "Foo"
end
end
module Bar
def f
puts "Bar"
super
end
end
class Foobar < Foo
include Bar
def f
puts "Foobar"
super
end
end
foobar = Foobar.new
foobar.f
# =>
# Foobar
# Bar
# Foo
而且我不相信可以从ruby环境本身访问这个'继承列表',这意味着这个功能将无法使用(但它很有用;我不确定这是否是预期的功能。)
答案 2 :(得分:0)
super
)你会引用给定方法的超级版本。
你不能简单地按名称调用方法,因为多态性的工作方式(如何根据对象类计算实际调用该方法的哪个版本)会导致调用自身的方法,旋转成一组无限的调用,并导致堆栈溢出。