Проблема с доступом к методам суперкласса в переопределениях методов - PullRequest
2 голосов
/ 13 декабря 2010

Мне трудно понять, когда можно назвать «супер», а когда нет. В приведенном ниже примере метод super приводит к ошибке отсутствия суперкласса.

class Bacterium
  def eats
    puts "Nam"
  end
end

class Bacterium
  def eats
    super # -> no superclass error
    puts "Yam"
  end
end

b = Bacterium.new
b.eats

Но это работает:

class Fixnum
  def times
    super # -> works
    puts "done"
  end
end

5.times { |i| puts i.to_s }

Является ли 5 ​​не только экземпляром Fixnum. И я не переопределяю существующий метод, как в примере Bacterium выше?

Ответы [ 2 ]

3 голосов
/ 13 декабря 2010

Как сказал Младен, вы можете проверить это с помощью Class#superclass:

irb> Fixnum.superclass
=> Integer

И реализует ли Integer #times?:

irb> Integer.instance_methods.grep /times/
=> [:times]

Да, это так.

Итак, в упрощенном виде, мы можем сказать, что super вызывает метод, которым вы являетесь в суперклассе. В вашем случае суперклассом Bacterium является Object, который не реализует #eats.

Я сказал, что это очень упрощено, потому что посмотрите на этот пример:

module One
  def hi
    " World" << super()
  end
end

module Two
  def hi
    "Hello" << super()
  end
end

class SayHi
  def hi
    "!!!"
  end
end

h = SayHi.new
h.extend(One)
h.extend(Two)

puts h.hi

#=> Hello World!!

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

Использовать Google-fu для "объектной модели Ruby" ...

3 голосов
/ 13 декабря 2010

Нет, не совсем. Fixnum наследуется от Integer класса, и вы на самом деле переопределяете Integer#times, поэтому super работает так, как он вызывает реализацию от родителя.

Чтобы добиться чего-то похожего при обезьяньей патчинге, вы должны использовать метод псевдонима перед его переопределением и вызывать его по псевдониму.

class Bacterium
  alias_method :eats_original, :eats
  def eats
    eats_original # -> "Nam"
    puts "Yam"
  end
end

Повторное открытие класса не является формой наследования, и super здесь бесполезен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...