Ответ 1
Подумайте о Enumerable.
Это прекрасный пример того, когда вам нужно включить его в модуль. Если ваш класс определяет #each
, вы получаете много добра, просто включив модуль (#map
, #select
и т.д.). Это единственный случай, когда я использую модули как mixins - когда модуль предоставляет функциональность с точки зрения нескольких методов, определенных в классе, который вы включите в модуль. Я могу утверждать, что это должен быть единственный случай вообще.
Что касается определения "статических" методов, лучшим подходом будет:
module MyModule
def self.do_something
end
end
Вам действительно не нужно вызывать #module_function
. Я думаю, что это просто странное наследие.
Вы можете даже сделать это:
module MyModule
extend self
def do_something
end
end
... но это не сработает, если вы также захотите включить модуль где-нибудь. Я предлагаю избегать этого, пока вы не изучите тонкости метапрограммирования Ruby.
Наконец, если вы просто выполните:
def do_something
end
... он не будет использоваться как глобальная функция, а как частный метод на Object
(в Ruby нет функций, просто методов). Есть два недостатка. Во-первых, у вас нет пространства имен - если вы определяете другую функцию с тем же именем, она получает оценку, которую вы получите позже. Во-вторых, если у вас есть функциональность, реализованная в терминах #method_missing
, использование частного метода в Object
будет теневым. И, наконец, патч обезьяны Object
- это просто злой бизнес:)
EDIT:
module_function
может использоваться так же, как private
:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
Таким образом, вы можете вызвать Something.bar
, но не Something.foo
. Если вы определяете другие методы после этого вызова на module_function
, они также будут доступны без перемешивания.
Мне это не нравится по двум причинам. Во-первых, модули, которые смешиваются и имеют "статические" методы, звучат немного изворотливыми. Могут быть действительные случаи, но это будет не так часто. Как я уже сказал, я предпочитаю использовать модуль как пространство имен или смешивать его, но не оба.
Во-вторых, в этом примере bar
также будет доступен для классов/модулей, которые смешиваются в Something
. Я не уверен, когда это желательно, поскольку либо метод использует self
, и его нужно смешивать, либо нет, и тогда его не нужно смешивать.
Я думаю, что использование module_function
без передачи имени метода используется довольно часто, чем с. То же самое касается private
и protected
.