Userò Java per la dimostrazione di codice / idea.
Immagina che sia necessario definire due interfacce: Observer e Observable ( observer Reticolo ). È una buona idea avere due interfacce generiche, quindi non c'è alcuna restrizione su ciò che viene osservato , chi lo sta osservando (sta addirittura usando i generici su questo?).
Java ha una Observable classe concreta (non finale) e un'interfaccia Observer . Devi delegare a gestire gli osservatori e a notificarli durante l'aggiornamento alla classe Observer concreta. Questo è un modo per implementare il modello. Non so se sia l'approccio migliore (probabilmente lo è), ma per il gusto di questo esempio supponiamo che ogni classe / tipo che vuole essere osservabile, debba implementare l'interfaccia Observable below e gestire tutto da solo.
Non dovremmo dimenticare che l'interfaccia / oggetto Observer e Observable originali sono stati implementati in JDK1.0, quando i generici non erano disponibili.
Ora la domanda: è una buona idea dichiarare semplicemente un tipo generico in un'interfaccia per indicare che la classe di implementazione deve essere consapevole di un tipo specifico? Oppure è un modo totalmente sbagliato di usare i generici?
See:
public interface Observable<T> {
// Only observers who are aware of type T are allowed.
// But should really Observable be concerned about it?
public void registerObserver(Observer<? extends T> o);
}
// The T here denotes that implementing class will be aware of a type called T,
// (not that it can operate on a range of types).
public interface Observer<T> {
// Observer is not aware of Observable interface directly. But it knows about T.
public void update(T arg);
}
VS
public interface Observable {
// Is it an observer? then it is allowed. That's all we need to know.
public void registerObserver(Observer o);
// Observers will be passed the instance of observable,
// then they call this method to fetch arg.
// something like:
// for(Observer o: this.observers) o.update(this);
public <T> T getArg();
}
public interface Observer {
// Pass me an Observable who returns T and i'll do the rest!
public void update(Observable o);
}
Sento che i farmaci generici sono completamente sbagliati.
P.S: Confrontando questo modo di implementare il modello di osservatore (chiedendo ad ogni tipo di re-implementare queste interfacce) rispetto alla soluzione java originale (delegazione) ci rendiamo conto che non è davvero una buona idea. Causa un sacco di codice duplicato. Ma aiuta a capire meglio i farmaci generici.
Aggiornamento Il vero problema con java.util.Observer
è notifyObservers(Object arg)
[link a doc] dove arg
è lanciato in fase di runtime dagli osservatori. Come possiamo evitare questo tipo di cast?