次の2つのインターフェイスがあるとします。
interface Readable {
public void read();
}
interface Writable {
public void write();
}
場合によっては、実装オブジェクトはこれらの1つしかサポートできませんが、多くの場合、実装は両方のインターフェイスをサポートします。インターフェイスを使用する人々は次のようなことをしなければなりません:
// 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();
これらのオプションはどれも非常に便利ではありません。これをメソッドパラメーターとして使用することを考えると、さらに便利です。
1つの解決策は、ラッピングインターフェイスを宣言することです。
interface TheWholeShabam extends Readable, Writable {}
リード・ライト可能の両方がサポートするすべての実装:しかし、これはある特定の問題がある持っている、彼らはインターフェイスを使用している人々との互換性を持つようにしたい場合はTheWholeShabamを実装することを。たとえ両方のインターフェースの存在が保証されていること以外は何も提供しませんが。
この問題に対する明確な解決策はありますか、それともラッパーインターフェイスを使用する必要がありますか?
更新
実際には、読み取りと書き込みの両方が可能なオブジェクトを用意する必要がある場合が多いので、単に引数の懸念を分離するだけでは必ずしもきれいな解決策とは限りません。
更新2
(回答として抽出されているため、コメントしやすくなっています)
更新3
これの主なユースケースはストリームではないことに注意してください(ただし、それらもサポートする必要があります)。ストリームは入力と出力を非常に明確に区別し、責任の明確な分離があります。むしろ、非常に特定の状態がアタッチされている1つのオブジェクトに書き込みと読み取りができる1つのオブジェクトが必要なバイトバッファのようなものを考えてください。これらのオブジェクトは、非同期I / O、エンコードなどのいくつかの場合に非常に役立つために存在します。
更新4
私が最初に試したものの1つは、以下に示す提案と同じでした(受け入れられた答えを確認してください)が、あまりにも壊れやすいことが判明しました。
型を返す必要があるクラスがあるとします:
public <RW extends Readable & Writable> RW getItAll();
このメソッドを呼び出す場合、ジェネリックRWはオブジェクトを受け取る変数によって決定されるため、この変数を記述する方法が必要です。
MyObject myObject = someInstance.getItAll();
これは機能しますが、もう一度実装に結び付け、実行時にクラスキャスト例外をスローする場合があります(返される内容によって異なります)。
さらに、RW型のクラス変数が必要な場合は、クラスレベルでジェネリックを定義する必要があります。