Supponiamo 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 è estremamente conveniente, tanto più se si considera che si desidera questo come parametro del metodo.
Una soluzione sarebbe dichiarare un'interfaccia di wrapping:
interface TheWholeShabam extends Readable, Writable {}
Ma questo ha un problema specifico: tutte le implementazioni che supportano sia Readable che Writable devono 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.
Esiste una soluzione pulita a questo problema o devo scegliere l'interfaccia del wrapper?
AGGIORNARE
In effetti è spesso necessario avere un oggetto che sia sia leggibile che scrivibile, quindi semplicemente separare le preoccupazioni negli argomenti non è sempre una soluzione pulita.
UPDATE2
(estratto come risposta, quindi è più facile commentare)
Update3
Si noti che il caso d'uso principale per questo non è flussi (anche se devono essere supportati anche loro). 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 su cui puoi scrivere e leggere, un oggetto a cui sia associato uno stato molto specifico. Questi oggetti esistono perché sono molto utili per alcune cose come I / O asincrono, codifiche, ...
Update4
Una delle prime cose che ho provato è stata la stessa del suggerimento riportato di seguito (controlla la risposta accettata) ma si è rivelata troppo fragile.
Supponiamo di avere una classe che deve restituire il tipo:
public <RW extends Readable & Writable> RW getItAll();
Se si chiama questo metodo, l'RW generico è determinato dalla variabile che riceve l'oggetto, quindi è necessario un modo per descrivere questo var.
MyObject myObject = someInstance.getItAll();
Ciò funzionerebbe, ma ancora una volta lo lega a un'implementazione e può effettivamente lanciare classcastexceptions in fase di esecuzione (a seconda di cosa viene restituito).
Inoltre, se si desidera una variabile di classe del tipo RW, è necessario definire il generico a livello di classe.