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, если бы таковой существовал).
Больше книг — больше знаний!
Заберите 20% скидку на все книги Литрес с нашим промокодом
ПОЛУЧИТЬ СКИДКУДанный текст является ознакомительным фрагментом.