С include
или prepend
вы можете получить доступ только к методам экземпляра модуля 1 .Поэтому вы можете спросить, есть ли какая-либо причина для определения методов модуля в модуле.Ответ звучит "да".Вы можете захотеть сделать это по двум причинам.
Первая не имеет ничего общего с включением или добавлением модуля.Вам нужно только взглянуть на модуль Math , чтобы понять, почему вы можете захотеть это сделать.Все методы, определенные в Math
, являются модульными методами.Они составляют библиотеку полезных функций.Это, конечно, методы, но, поскольку все они имеют Math
в качестве получателя, они ведут себя как функции в не-ООП-языках.
Вторая причина заключается в том, что вам может потребоваться определить метод обратного вызова (он же hook метод) для модуля, который должен быть включен или добавлен другим модулем.Основными из них являются Модуль # включен , Модуль # с добавлением , Модуль # расширен , Класс # наследуется и BasicObject # method_missing.Последний из них является методом экземпляра;остальные являются модульными методами.Ниже приведен пример Module#prepended
.
@ mudasoba показал, как ограничить методы экземпляра подмодулем Sub
из Mod
, чтобы Mod::Sub
можно было добавить (или включить) вкласс (или модуль) синглтон-класс.Обычно используемый шаблон для выполнения этого обратного вызова Module#prepended
.Это следует.
module PrependedModule
module ClassMethods
def klass_method
puts 'PrependedModule klass_method'
end
end
def instance_method_a
puts 'PrepenedModule instance method'
end
def self.prepended(mod)
mod.singleton_class.prepend(ClassMethods)
end
end
class SomeClass
def self.klass_method
puts 'SomeClass klass_method'
end
def instance_method_a
puts 'SomeClass instance_method'
end
prepend PrependedModule
end
SomeClass.klass_method
# PrependedModule klass_method
SomeClass.new.instance_method_a
# PrepenedModule instance method
1 Мне всегда было любопытно, что методы экземпляра могут быть определены для модулей (которые не являются классами), учитывая, что такие модули не могут иметьэкземпляров.Правда, эти методы становятся методами экземпляров в классах, которые включают или дополняют модуль, но имейте в виду, что эти модули могут быть включены или дополнены другими модулями (которые не являются классами).Поэтому можно ожидать, что такие методы будут иметь имя, отличное от «метода экземпляра».Однако найти подходящую альтернативу было бы непросто, что, возможно, является одной из причин сохранения этой номенклатуры.