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

时间:2021-10-30 05:30:05

In Ruby, super is a keyword rather than a method.

在Ruby中,super是关键字而不是方法。

Why was it designed this way?

为什么这样设计?

Ruby's design tends toward implementing as much as possible as methods; keywords are usually reserved for language features that have their own grammar rules. super, however, looks and acts like a method call.

Ruby的设计倾向于尽可能多地实现方法;关键字通常保留用于具有自己的语法规则的语言功能。然而,超级看起来像一个方法调用。

(I know it would be cumbersome to implement super in pure Ruby, since it would have to parse the method name out of caller, or use a trace_func. This alone wouldn't prevent it from being a method, because plenty of Kernel's methods are not implemented in pure Ruby.)

(我知道在纯Ruby中实现super会很麻烦,因为它必须从调用者中解析出方法名,或者使用trace_func。仅这一点不会阻止它成为一个方法,因为很多内核的方法都是没有在纯Ruby中实现。)

3 个解决方案

#1


5  

It behaves a little differently, in that if you don't pass arguments, all of the current arguments (and block, if present) are passed along... I'm not sure how that would work as a method.

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

To give a rather contrived example:

给出一个相当人为的例子:

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

I did not need to handle the yield, or pass the arguments to super. In the cases where you specifically want to pass different arguments, then it behaves more like a method call. If you want to pass no arguments at all, you must pass empty parentheses (super()).

我不需要处理yield,也不需要将参数传递给super。在您特别想要传递不同参数的情况下,它的行为更像是方法调用。如果您想要根本不传递任何参数,则必须传递空括号(super())。

It simply doesn't have quite the same behaviour as a method call.

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

#2


1  

super doesn't automatically call the parent class's method. If you imagine the inheritance hierarchy of a ruby class as a list, with the class at the bottom and Object at the top, when ruby sees the the super keyword, rather than just check the the parent class, it moves up the entire list until it finds the first item that has a method defined with that name.

super不会自动调用父类的方法。如果您将ruby类的继承层次结构想象为列表,底层的类和顶部的Object,当ruby看到super关键字时,而不是仅检查父类,它会向上移动整个列表,直到它找到第一个具有使用该名称定义的方法的项目。

I'm careful to say item because it could also be a module. When you include a module in to a class, it is wrapped in an anonymous superclass and put above your class in the list I talked about before, so that means if you had a method defined for your class that was also defined in the module, then calling super from the class's implementation would call the module's implementation, and not the parent class's:

我小心说项目因为它也可能是一个模块。当你将一个模块包含在一个类中时,它被包装在一个匿名的超类中,并放在我之前讨论的列表中的类之上,这意味着如果你有一个为你的类定义的方法,也是在模块中定义的,然后从类的实现中调用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

And I don't believe that it is possible to access this 'inheritance list' from the ruby environment itself, which would mean this functionality would not be available (However useful it is; I'm not every sure if this was an intended feature.)

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

#3


0  

Hm, good qustion. I'm not sure how else (besides using super) you would you reference the super version of a given method.

嗯,好脾气。我不确定如何(除了使用super)你会引用给定方法的超级版本。

You can't simply call the method by name, because the way that polymorphism works (how it figures out which version of that method to actually call, based on the object class) would cause your method to call itself, spinning into an infinite set of calls, and resulting in a stack overflow.

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

#1


5  

It behaves a little differently, in that if you don't pass arguments, all of the current arguments (and block, if present) are passed along... I'm not sure how that would work as a method.

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

To give a rather contrived example:

给出一个相当人为的例子:

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

I did not need to handle the yield, or pass the arguments to super. In the cases where you specifically want to pass different arguments, then it behaves more like a method call. If you want to pass no arguments at all, you must pass empty parentheses (super()).

我不需要处理yield,也不需要将参数传递给super。在您特别想要传递不同参数的情况下,它的行为更像是方法调用。如果您想要根本不传递任何参数,则必须传递空括号(super())。

It simply doesn't have quite the same behaviour as a method call.

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

#2


1  

super doesn't automatically call the parent class's method. If you imagine the inheritance hierarchy of a ruby class as a list, with the class at the bottom and Object at the top, when ruby sees the the super keyword, rather than just check the the parent class, it moves up the entire list until it finds the first item that has a method defined with that name.

super不会自动调用父类的方法。如果您将ruby类的继承层次结构想象为列表,底层的类和顶部的Object,当ruby看到super关键字时,而不是仅检查父类,它会向上移动整个列表,直到它找到第一个具有使用该名称定义的方法的项目。

I'm careful to say item because it could also be a module. When you include a module in to a class, it is wrapped in an anonymous superclass and put above your class in the list I talked about before, so that means if you had a method defined for your class that was also defined in the module, then calling super from the class's implementation would call the module's implementation, and not the parent class's:

我小心说项目因为它也可能是一个模块。当你将一个模块包含在一个类中时,它被包装在一个匿名的超类中,并放在我之前讨论的列表中的类之上,这意味着如果你有一个为你的类定义的方法,也是在模块中定义的,然后从类的实现中调用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

And I don't believe that it is possible to access this 'inheritance list' from the ruby environment itself, which would mean this functionality would not be available (However useful it is; I'm not every sure if this was an intended feature.)

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

#3


0  

Hm, good qustion. I'm not sure how else (besides using super) you would you reference the super version of a given method.

嗯,好脾气。我不确定如何(除了使用super)你会引用给定方法的超级版本。

You can't simply call the method by name, because the way that polymorphism works (how it figures out which version of that method to actually call, based on the object class) would cause your method to call itself, spinning into an infinite set of calls, and resulting in a stack overflow.

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