Прояснение метода перекрытия рубиновой смеси
Я только что столкнулся с таким поведением, которого я действительно не понимаю.
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"
Это похоже на то, что модуль каким-то образом включен до определения метода экземпляра класса. Не могли бы вы прояснить?
Ответы
Ответ 1
От программирования раздела Ruby на mixins:
Фактически, смешанные модули эффективно ведут себя как суперклассы.
Итак, что вы переживаете, это нормально.
ваш модуль M является суперклассом вашего класса C
Поэтому ваш метод foo в классе C переопределяет метод foo в модуле M
Ответ 2
Здесь как ruby выполняет поиск метода:
- класс однопользовательских приемников;
- класс приемника;
- любые включенные модули;
- повторите поиск в супер-классе приемника;
- если метод вообще не найден, вызов method_missing;
Здесь вы можете найти более подробную информацию: http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html
Поэтому, чтобы найти метод, Ruby входит в класс приемника, и оттуда он поднимается на цепочку предков до тех пор, пока не найдет метод. Это поведение также называется "одним шагом вправо, а затем вверх", правило: перейдите на один шаг вправо в класс приемника, а затем вверх цепь предков, пока вы не найдете метод. Когда вы включаете модуль в классе (или даже в другом модуле), Ruby создает анонимный класс, который обертывает модуль и вставляет анонимный класс в цепочке, чуть выше самого включенного класса.