为什么'super'是关键字而不是Ruby中的方法?

时间:2011-12-10 04:24:22

标签: ruby language-design super

在Ruby中,superkeyword而不是方法。

为什么这样设计?

Ruby的设计倾向于尽可能多地实现方法;关键字通常保留用于具有自己的语法规则的语言功能。但是,super的外观和行为类似于方法调用。

(我知道在纯Ruby中实现super会很麻烦,因为它必须从calleruse a trace_func解析方法名称。防止它成为一个方法,因为大量的Kernel方法没有在纯Ruby中实现。)

3 个答案:

答案 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)你会引用给定方法的超级版本。

你不能简单地按名称调用方法,因为多态性的工作方式(如何根据对象类计算实际调用该方法的哪个版本)会导致调用自身的方法,旋转成一组无限的调用,并导致堆栈溢出。