Piense en Enumerable.
Este es el ejemplo perfecto de cuándo debe incluirlo en un módulo. Si su clase define #each
, obtiene mucha bondad con solo incluir un módulo (#map
, #select
, etc.). Este es el único caso cuando uso módulos como mixins, cuando el módulo proporciona funcionalidad en términos de unos pocos métodos, definidos en la clase en la que se incluye el módulo. Puedo argumentar que este debería ser el único caso en general.
En cuanto a la definición de métodos "estáticos", un mejor enfoque sería:
module MyModule
def self.do_something
end
end
Usted realmente no necesita llamar #module_function
. Creo que es solo un legado extraño.
incluso Usted puede hacer esto:
module MyModule
extend self
def do_something
end
end
... pero no va a funcionar bien si también desea incluir el módulo en alguna parte. Sugiero evitarlo hasta que aprenda las sutilezas de la metaprogramación de Ruby.
Por último, si usted acaba de hacer:
def do_something
end
, ... no terminan como una función global, sino como un método privado en Object
(no hay ninguna función en Ruby, a métodos). Hay dos desventajas. En primer lugar, no tiene espacio de nombres: si define otra función con el mismo nombre, es la que se evalúa más adelante. En segundo lugar, si tiene la funcionalidad implementada en términos de #method_missing
, tener un método privado en Object
lo sombreará. Y, por último, mono parches Object
es sólo el mal negocio :)
EDIT:
module_function
se puede utilizar de una manera similar a private
:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
De esta manera, se puede llamar Something.bar
, pero no no Something.foo
. Si define otros métodos después de esta llamada al module_function
, también estarían disponibles sin mezclar.
No me gusta por dos razones.En primer lugar, los módulos que están mezclados y tienen métodos "estáticos" suenan un poco dudosos. Puede haber casos válidos, pero no será tan seguido. Como dije, prefiero usar un módulo como espacio de nombres o mezclarlo, pero no ambos.
En segundo lugar, en este ejemplo, bar
también estaría disponible para las clases/módulos que se mezclan en Something
. No estoy seguro de cuándo es deseable, ya que el método usa self
y debe mezclarse, o no, y luego no necesita mezclarse.
Creo que usar module_function
sin pasar el El nombre del método se usa con bastante más frecuencia que con. Lo mismo vale para private
y protected
.
gracias por la explicación. Entiendo por qué querría mezclar en un módulo, mi pregunta era más acerca de cuándo podría usar realmente la función module_function. ¿Hay algún momento en que puedas usarlo? –
Hay una captura más en este último ejemplo con 'module_function': La función" privada "' foo' no se puede acceder desde dentro de 'bar', porque' foo' es entonces un método de instancia (no tiene 'self') , y solo se puede invocar cuando este módulo está mezclado en alguna clase. Imposible cuando es un módulo independiente solo para propósitos de creación de espacios de nombres. Entonces, ¿cómo tener ambas cosas? ¿Cómo se usa el módulo solo para el espaciado de nombres y se ocultan algunas funciones de ayuda de implementación del mundo exterior, pero se les permite llamar por sus métodos de interfaz? – SasQ