Разъяснение метода переопределения в Ruby mixin - PullRequest
12 голосов
/ 22 марта 2012

Я только что столкнулся с таким поведением, которое я на самом деле не понимаю.

module M
  def foo
    "module_foo"
  end
end

class C
  def foo
    "class_foo"
  end
  include M
end

puts C.new.foo

Почему C.new.foo фактически возвращает class_foo?Я был почти уверен, что метод должен быть переопределен тем, что в модуле.Другое дело, замена "class_foo" на super приводит к C.new.foo return `" module_foo "

Это выглядит так, как будто модуль каким-то образом включен до определения метода экземпляра класса.Не могли бы вы уточнить?

Ответы [ 2 ]

15 голосов
/ 22 марта 2012

С Программирование раздела Ruby на миксинах:

Фактически, смешанные модули эффективно ведут себя как суперклассы.

Итак, что вы испытываетенормально.Ваш Модуль M является суперклассом вашего класса C

Поэтому ваш метод foo в классе C переопределяет метод foo в модуле M

3 голосов
/ 22 марта 2012

Вот как ruby ​​выполняет поиск метода:

  1. синглтон-класс получателя;
  2. класс получателя;
  3. любые включенные методы модулей;
  4. повторпоиск в суперклассе получателя;
  5. , если метод вообще не найден, вызов метода_missing;

Более подробную информацию можно найти здесь: http://ruby -metaprogramming.rubylearning.com / html / ruby_metaprogramming_2.html

Поэтому, чтобы найти метод, Ruby переходит в класс получателя и оттуда поднимается по цепочке предков, пока не найдет метод,Это поведение также называется правилом «один шаг вправо, затем вверх»: перейдите на один шаг вправо в класс получателя, а затем вверх по цепочке предков, пока не найдете метод.Когда вы включаете модуль в класс (или даже в другой модуль), Ruby создает анонимный класс, который оборачивает модуль и вставляет анонимный класс в цепочку, чуть выше самого включающего класса.

...