Suponha que você tenha duas interfaces:
interface Readable {
public void read();
}
interface Writable {
public void write();
}
Em alguns casos, os objetos de implementação podem suportar apenas um deles, mas em muitos casos as implementações suportam as duas interfaces. As pessoas que usam as interfaces terão que fazer algo como:
// 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();
Nenhuma dessas opções é extremamente conveniente, ainda mais quando se considera que você deseja isso como um parâmetro de método.
Uma solução seria declarar uma interface de agrupamento:
interface TheWholeShabam extends Readable, Writable {}
Mas isso tem um problema específico: todas as implementações que suportam Readable e Writable precisam implementar o TheWholeShabam se quiserem ser compatíveis com as pessoas que usam a interface. Mesmo que não ofereça nada além da presença garantida de ambas as interfaces.
Existe uma solução limpa para esse problema ou devo usar a interface do wrapper?
ATUALIZAR
De fato, muitas vezes é necessário ter um objeto que seja legível e gravável, de modo que simplesmente separar as preocupações dos argumentos nem sempre seja uma solução limpa.
UPDATE2
(extraído como resposta, para ficar mais fácil comentar)
UPDATE3
Por favor, tome cuidado para que a principal base de dados para isso não seja fluxos (embora eles também devam ser suportados). Os fluxos fazem uma distinção muito específica entre entrada e saída e há uma clara separação de responsabilidades. Em vez disso, pense em algo como um bytebuffer no qual você precisa de um objeto no qual possa escrever e ler, um objeto que tenha um estado muito específico anexado. Esses objetos existem porque são muito úteis para algumas coisas como E / S assíncrona, codificações, ...
UPDATE4
Uma das primeiras coisas que tentei foi a mesma sugerida abaixo (verifique a resposta aceita), mas provou ser muito frágil.
Suponha que você tenha uma classe que precise retornar o tipo:
public <RW extends Readable & Writable> RW getItAll();
Se você chamar esse método, o RW genérico será determinado pela variável que recebe o objeto, portanto, você precisará de uma maneira de descrever essa var.
MyObject myObject = someInstance.getItAll();
Isso funcionaria, mas, mais uma vez, vincula-o a uma implementação e pode realmente lançar as exceções de classes de classe em tempo de execução (dependendo do que é retornado).
Além disso, se você deseja uma variável de classe do tipo RW, precisa definir o genérico no nível da classe.