Quali sono alcuni buoni esempi di Mixin e/o Tratti?
-
21-08-2019 - |
Domanda
Stavo leggendo Ruby e ho imparato a conoscere il suo modello di mixin, ma non riuscivo a pensare a molte funzionalità di mixin utili (perché molto probabilmente non sono abituato a pensare in questo modo).Quindi mi chiedevo quali sarebbero dei buoni esempi di utile funzionalità Mixin?
Grazie
Modificare:Un po' di background.Vengo dal C++ e da altri linguaggi a oggetti, ma il mio dubbio qui è che Ruby dica che non eredita i mixin, ma continuo a vedere i mixin come ereditarietà multipla, quindi temo che sto cercando di classificarli troppo presto nella mia zona di comfort , e non capisco davvero cosa sia un mixin.
Soluzione
Bene il solito esempio credo sia Persistenza
module Persistence
def load sFileName
puts "load code to read #{sFileName} contents into my_data"
end
def save sFileName
puts "Uber code to persist #{@my_data} to #{sFileName}"
end
end
class BrandNewClass
include Persistence
attr :my_data
def data=(someData)
@my_data = someData
end
end
b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"
Immaginate il modulo è stato scritto da un ninja Ruby, che persiste lo Stato della classe in un file.
Ora supponiamo che io scrivo una nuova classe di zecca, posso riutilizzare la funzionalità di persistenza mescolandolo nel dicendo include ModuleILike
. Si può anche includere moduli a runtime. Ottengo caricare e salvare i metodi gratis semplicemente mescolando in. Questi metodi sono proprio come quelli che lei stesso ha scritto per la classe. Codice / Comportamento / Funzionalità-riutilizzo senza eredità!
Quindi quello che stai facendo è compreso metodi alla tabella di metodo per la classe (non letteralmente corretti ma chiudi).
Altri suggerimenti
Di solito sono utilizzati per aggiungere una qualche forma di funzionalità standard a una classe, senza dover ridefinire tutto. Probabilmente si può pensare di loro un po 'come le interfacce in Java, ma invece di definire un elenco di metodi che devono essere implementati, molti di loro sarà effettivamente essere implementata includendo il modulo.
Ci sono alcuni esempi nella libreria standard:
Singleton - Un modulo che può essere miscelato in ogni classe per renderlo un Singleton. Il metodo di inizializzazione è fatto privato, e un metodo di istanza aggiunto, che assicura che non v'è sempre e solo un esempio di quella classe nell'applicazione.
Paragonabile - Se si include questo modulo in una classe, che definisce il metodo <=>, che confronta l'istanza corrente con un altro oggetto e dice che è più grande, è abbastanza per fornire <, <=, ==,> =, > e mezzo? metodi.
Enumerable - Mescolando in questo modulo, e la definizione di un ogni metodo, si ottiene il supporto per tutti gli altri metodi correlati, come raccolta, iniettare, selezionare e rifiutare. Se è anche ottenuto il metodo <=>, allora sarà anche il supporto sorta, min e max.
DataMapper è anche un interessante esempio di cosa può essere fatto con una semplice istruzione include, prendendo una classe standard, e aggiungendo la capacità di persistere in un archivio dati.
In Ruby, la ragione per cui i Mixin non sono ereditarietà multipla è che la combinazione dei metodi di mixin è una cosa da fare una volta sola.Questo non sarebbe un grosso problema, tranne per il fatto che i moduli e le classi di Ruby sono aperti a modifiche.Ciò significa che se mescoli un modulo alla tua classe, aggiungi un metodo al modulo, il metodo non lo farà essere disponibile per la tua classe;dove se lo facessi nell'ordine opposto, lo farebbe.
È come ordinare un cono gelato.Se prendi confettini di cioccolato e pezzetti di caramello come mixin e te ne vai con il tuo cono, il tipo di cono gelato che hai non cambierà se qualcuno aggiunge confettini multicolori al contenitore dei confettini di cioccolato in gelateria.La tua classe, il cono gelato, non viene modificata quando lo è il modulo di miscelazione, il contenitore dei confettini.La prossima persona che utilizzerà quel modulo di mixin vedrà i cambiamenti.
Quando tu include
un modulo in Ruby, chiama Module#append_features
su quel modulo, che aggiunge una copia dei metodi di quel modulo all'include una volta.
L'ereditarietà multipla, a quanto ho capito, è più simile alla delega.Se la tua classe non sa come fare qualcosa, lo chiede ai suoi genitori.In un ambiente di classe aperta, i genitori di una classe potrebbero essere stati modificati dopo la creazione della classe.
È come una relazione genitore-figlio RL.Tua madre potrebbe aver imparato a fare il giocoliere dopo la tua nascita, ma se qualcuno ti chiede di fare il giocoliere e tu glielo chiedi:mostrarti come (copiarlo quando ne hai bisogno) o farlo per te (pura delega), allora lei sarà in grado a quel punto, anche se sei stato creato prima che lo fosse la sua capacità di destreggiarsi.
È possibile che tu possa modificare un modulo Ruby 'include' per agire più come un'ereditarietà multipla modificando Module#append_features
per mantenere un elenco di includer e quindi aggiornarli utilizzando il file method_added
callback, ma questo rappresenterebbe un grande cambiamento rispetto allo standard Ruby e potrebbe causare grossi problemi quando si lavora con altri codici.Potrebbe essere meglio creare un file Module#inherit
metodo che ha chiamato include
e ha gestito anche la delega.
Per quanto riguarda un esempio del mondo reale, Enumerable
è fantastico.Se definisci #each
e includere Enumerable
nella tua classe, questo ti dà accesso a tutta una serie di iteratori, senza che tu debba codificarli tutti.
E 'in gran parte utilizzato come si potrebbe usare l'ereditarietà multipla in C ++ o interfacce di applicazione in Java / C #. Non sono sicuro di dove la vostra esperienza si trova, ma se avete fatto queste cose prima, mixins sono come li farebbe in Ruby. E 'un modo sistematizzato di iniettare funzionalità in classi.