Почему «супер» - это ключевое слово, а не метод в Ruby? - PullRequest
9 голосов
/ 10 декабря 2011

В Ruby super является ключевым словом , а не методом.

Почему он был разработан таким образом?

Дизайн Руби направлен на реализацию как можно большего количества методов; ключевые слова обычно зарезервированы для языковых функций, которые имеют свои собственные правила грамматики. super, однако, выглядит и действует как вызов метода.

(я знаю, что было бы обременительно реализовывать super в чистом Ruby, поскольку ему пришлось бы анализировать имя метода из caller, или использовать trace_func . Это само по себе не не позволяйте ему быть методом, потому что множество Kernel методов не реализованы в чистом Ruby.)

Ответы [ 3 ]

5 голосов
/ 11 декабря 2011

Он ведет себя немного иначе, в том случае, если вы не передаете аргументы, все текущие аргументы (и блок, если есть) передаются вместе ... Я не уверен, как это будет работать как метод.

Чтобы привести довольно надуманный пример:

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

Мне не нужно обрабатывать выход или передавать аргументы в super.В тех случаях, когда вы специально хотите передать разные аргументы, он ведет себя больше как вызов метода.Если вы вообще не хотите передавать аргументы, вы должны передать пустые скобки (super()).

Он просто не имеет такого же поведения, как и вызов метода.

1 голос
/ 10 декабря 2011

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., что означало бы, что эта функциональность не будет доступна (какой бы полезной она ни была; я не всегда уверен, была ли эта функция предполагаемой).

0 голосов
/ 10 декабря 2011

Хм, хорошее питание. Я не уверен, как еще (кроме использования super) вы бы сослались на супер версию данного метода.

Вы не можете просто вызвать метод по имени, потому что способ, которым работает полиморфизм (как он выясняет , какую версию этого метода на самом деле вызвать, основываясь на классе объекта), вызвал бы ваш метод вызывать себя, вращаясь в бесконечном множестве вызовов и приводя к переполнению стека.

...