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

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

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, если бы таковой существовал).

Оглавление книги


Генерация: 1.150. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз