Supponi di avere due interfacce:
interface Readable {
public void read();
}
interface Writable {
public void write();
}
In alcuni casi gli oggetti di implementazione possono supportare solo uno di questi, ma in molti casi le implementazioni supporteranno entrambe le interfacce. Le persone che usano le interfacce dovranno fare qualcosa del tipo:
// can't write to it without explicit casting
Readable myObject = new MyObject();
// can't read from it without explicit casting
Writable myObject = new MyObject();
// tight coupling to actual implementation
MyObject myObject = new MyObject();
Nessuna di queste opzioni è terribilmente conveniente, ancor più se si considera che si vuole che questo sia un parametro del metodo.
Una soluzione sarebbe dichiarare un'interfaccia di avvolgimento:
interface TheWholeShabam extends Readable, Writable {}
Ma questo ha un problema specifico: tutte le implementazioni che supportano sia Readable che Writable hanno per implementare TheWholeShabam se vogliono essere compatibili con le persone che usano l'interfaccia. Anche se non offre nulla a parte la presenza garantita di entrambe le interfacce.
C'è una soluzione pulita a questo problema o dovrei andare per l'interfaccia wrapper?
Aggiorna
In effetti è spesso necessario avere un oggetto che sia sia leggibile sia scrivibile, in modo da separare semplicemente le preoccupazioni negli argomenti non è sempre una soluzione pulita.
UPDATE2
(estratto come risposta, quindi è più facile commentare)
Update3
Fai attenzione che il caso d'uso principale per questo è not (anche se devono essere supportati). Gli stream fanno una distinzione molto specifica tra input e output e c'è una chiara separazione delle responsabilità. Piuttosto, pensa a qualcosa come un bytebuffer in cui hai bisogno di un oggetto da cui puoi scrivere e leggere, un oggetto che ha uno stato molto specifico ad esso collegato. Questi oggetti esistono perché sono molto utili per alcune cose come l'I / O asincrono, le codifiche, ...
Update4
Una delle prime cose che ho provato era la stessa del suggerimento indicato di seguito (controlla la risposta accettata) ma si è dimostrato troppo fragile.
Supponiamo di avere una classe che deve restituire il tipo:
public <RW extends Readable & Writable> RW getItAll();
Se chiami questo metodo, la RW generica viene determinata dalla variabile che riceve l'oggetto, quindi hai bisogno di un modo per descrivere questa var.
MyObject myObject = someInstance.getItAll();
Funzionerebbe, ma ancora una volta lo legherà a un'implementazione e potrebbe lanciare classcastexceptions in fase di esecuzione (a seconda di cosa viene restituito).
Inoltre se vuoi una variabile di classe del tipo RW, devi definire il generico a livello di classe.