Программирование на языке Ruby.

11.2.7. Как работает включение модулей?

Когда модуль включается в класс, Ruby на самом деле создает прокси-класс, являющийся непосредственным родителем данного класса. Возможно, вам это покажется интуитивно очевидным, возможно, нет. Все методы включаемого модуля «маскируются» методами, определенными в классе.

Module MyMod.

 def meth.

  "из модуля".

 end.

End.

Class ParentClass.

 def meth.

  "из родителя".

 end.

End.

Class ChildClass < ParentClass.

 include MyMod.

 def meth.

  "из потомка".

 end.

End.

X = ChildClass.new p.

P x.meth # Из потомка.

Выглядит это как настоящее наследование: все, что потомок переопределил, становится действующим определением вне зависимости от того, вызывается ли include до или после переопределения.

Вот похожий пример, в котором метод потомка вызывает super, а не просто возвращает строку. Как вы думаете, что будет возвращено?

# Модуль MyMod и класс ParentClass не изменились.

Class ChildClass < ParentClass.

 include MyMod.

 def meth.

  "Из потомка: super = " + super.

 end.

End.

X = ChildClass.new.

P x.meth # Из потомка: super = из модуля.

Отсюда видно, что модуль действительно является новым родителем класса. А что если мы точно также вызовем super из модуля?

Module MyMod.

 def meth.

  "Из модуля: super = " + super.

 end.

End.

# ParentClass не изменился.

Class ChildClass < ParentClass.

 include MyMod.

 def meth.

  "Из потомка: super = " + super.

 end.

End.

X = ChildClass.new.

P x.meth # Из потомка: super = из модуля: super = из родителя.

Метод meth, определенный в модуле MyMod, может вызвать super только потому, что в суперклассе (точнее, хотя бы в одном из его предков) действительно есть метод meth. А что произошло бы, вызови мы этот метод при других обстоятельствах?

Module MyMod.

 def meth.

  "Из модуля: super = " + super.

 end.

End.

Class Foo include MyMod.

End.

X = Foo.new.

X.meth.

При выполнении этого кода мы получили бы ошибку NoMethodError (или обращение к методу method_missing, если бы таковой существовал).