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

为什么是';超级';Ruby中的关键字而不是方法?,ruby,language-design,super,Ruby,Language Design,Super,在Ruby中,是一个而不是一个方法 为什么它是这样设计的 Ruby的设计倾向于实现尽可能多的方法;关键字通常是为具有自己语法规则的语言功能保留的super在外观和行为上都类似于方法调用 (我知道在纯Ruby中实现super会很麻烦,因为它必须从caller中解析方法名,或者。这本身并不能阻止它成为一个方法,因为很多的方法不是在纯Ruby中实现的。)嗯,好问题。我不知道你还会如何引用给定方法的超级版本(除了使用super) 您不能简单地按名称调用该方法,因为多态性的工作方式(它如何根据对象类确定实

在Ruby中,是一个而不是一个方法

为什么它是这样设计的

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


(我知道在纯Ruby中实现
super
会很麻烦,因为它必须从
caller
中解析方法名,或者。这本身并不能阻止它成为一个方法,因为很多的方法不是在纯Ruby中实现的。)

嗯,好问题。我不知道你还会如何引用给定方法的超级版本(除了使用
super


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

super
不会自动调用父类的方法。如果您将ruby类的继承层次结构想象为一个列表,类位于底部,对象位于顶部,当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
class-Foo
def f
放“福”
结束
结束
模块条
def f
“酒吧”
超级的
结束
结束
类Foobar
#福巴
#酒吧
#福

我不相信从ruby环境本身访问这个“继承列表”是可能的,这意味着这个功能将不可用(不管它有多有用;我不确定这是否是一个预期的功能)。

它的行为有点不同,如果不传递参数,所有当前参数(和块,如果存在)都将传递给。。。我不确定这将如何作为一种方法工作

举一个相当做作的例子:

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
A类
def示例(a、b、c)
产生(a,b)+c
结束
结束
B类
我不需要处理产量,也不需要将参数传递给
super
。在您特别希望传递不同参数的情况下,它的行为更像是方法调用。如果不想传递任何参数,则必须传递空括号(
super()


它的行为与方法调用不同。

它的行为稍有不同,因为如果不传递参数,则所有当前参数(以及块,如果存在)都会被传递。。。我不确定这将如何作为一种方法。@d11wtq给出了正确的理由,也许它应该是一个答案而不是一个评论?@d11wtq:这是一个很好的观点,请给出一个答案。我确实想到了这一点,但我想知道这是否是唯一的原因。根据要求添加了我的评论作为答案,并举例说明(不是为你,而是为未来的读者):)当你说“该方法的超级版本”时,请你澄清哪种方法是“该方法”?对不起,澄清了一点措辞。我的意思是,“有问题的方法——不管你在说什么方法。”你可以通过从超类中获取
UnboundMethod
对象并将其绑定到子类实例,独立于子类已经覆盖它的事实来调用超类。例如
SuperKlass.instance\u方法(:foo).bind(SubKlass.new).call(arguments)
我不是问为什么
super
存在,我是问为什么它是一个关键字,而不是内核上的方法。如果是的话,你仍然可以像现在一样调用
super
Class#祖先
给你一个“继承列表”,所以这很简单,正如我在问题中指出的,
Kernel#super
不必用纯Ruby实现,Kernel
上的许多方法都是用C实现的(至少在核磁共振成像中)@riffraf是的,是的,但是当你在一个实例上使用
extend
时问题就出现了。因此,比方说,
Foobar
不包括module
Bar
,而是我扩展了
Foobar
Foobar.extend Bar
。在这一点上,如果你检查了
类#祖先
的返回值
Bar
不会出现在其中。(也就是说,如果您选中了
Foobar.Orients
或者如果您选中了
Foobar.class.Orients
)啊,是的,但是如果您查看singleton类,仍然可以看到它们:
(类我认为你的答案最重要的方面是,方法无法知道调用它时是否使用了括号。因为
super
是一个关键字,所以这个决定被烘焙到语法本身中。我相当肯定,尽管不确定,Ruby的内部将提供对参数和bl的访问打电话的人的名字。