Pensa a Enumerable.
Questo è l'esempio perfetto di quando è necessario includerlo in un modulo. Se la classe definisce #each
, si ottiene un sacco di bontà solo includendo un modulo (#map
, #select
, ecc.). Questo è l'unico caso in cui utilizzo i moduli come mixin - quando il modulo fornisce funzionalità in termini di alcuni metodi, definiti nella classe in cui è incluso il modulo. Posso sostenere che questo dovrebbe essere l'unico caso in generale.
Per quanto riguarda la definizione di metodi "statici", un approccio migliore sarebbe:
module MyModule
def self.do_something
end
end
non si ha realmente bisogno di chiamare #module_function
. Penso che sia solo una questione strana.
Si può anche fare questo:
module MyModule
extend self
def do_something
end
end
... ma non funziona bene se si vuole includere anche il modulo da qualche parte. Suggerisco di evitarlo fino a quando non imparerai le sottigliezze della metaprogrammazione di Ruby.
Infine, se lo farete:
def do_something
end
... esso non finire come una funzione globale, ma come un metodo privato su Object
(non ci sono funzioni in Ruby, a soli metodi). Ci sono due aspetti negativi. Innanzitutto, non disponi di namespace: se definisci un'altra funzione con lo stesso nome, è quella che verrà valutata in seguito. In secondo luogo, se la funzionalità è implementata in termini di #method_missing
, l'utilizzo di un metodo privato in Object
lo ombreggia. E, infine, la scimmia patch Object
sono affari solo male :)
EDIT:
module_function
può essere utilizzato in modo simile a private
:
module Something
def foo
puts 'foo'
end
module_function
def bar
puts 'bar'
end
end
In questo modo, è possibile chiamare Something.bar
, ma non non Something.foo
. Se si definiscono altri metodi dopo questa chiamata a module_function
, sarebbero anche disponibili senza mescolare.
Non mi piace per due motivi, però.Innanzitutto, i moduli che sono entrambi mixati e con metodi "statici" sembrano un po 'ambigui. Potrebbero esserci casi validi, ma non sarà così spesso. Come ho detto, preferisco usare un modulo come spazio dei nomi o mescolarlo, ma non entrambi.
In secondo luogo, in questo esempio, bar
sarebbe anche disponibile per classi/moduli che si mescolano in Something
. Non sono sicuro quando questo sia desiderabile, dal momento che il metodo usa o self
e deve essere mischiato o no e quindi non è necessario che venga mescolato.
Penso di usare module_function
senza passare il nome del metodo è usato molto più spesso rispetto a. Lo stesso vale per private
e protected
.
grazie per la spiegazione. Capisco perché vorresti mescolare un modulo, la mia domanda riguardava di più quando potresti effettivamente usare la funzione module_function. C'è qualche volta che potresti effettivamente usarlo? –
C'è un altro problema in questo ultimo esempio con 'module_function': La funzione" privata "' foo' non è accessibile da 'bar', perché' pippo' è quindi un metodo di istanza (non ha 'self') e può essere chiamato solo quando questo modulo è mescolato in qualche classe. Impossibile quando è un modulo standalone solo per scopi di namespace. Quindi come averlo entrambi? Come usare il modulo solo per namespacing e nascondere alcune funzioni di helper di implementazione dal mondo esterno, ma consentire loro di essere chiamati con i suoi metodi di interfaccia? – SasQ