java.io.OutputStream
抽象クラスではなくインターフェイスとしてモデル化されていないのはなぜですか?
インターフェースは、たとえば単体テストに役立つことが証明できると思いました。
一部のメソッドはすでに実装されています。これはインターフェースでは不可能です。
close()
void flush()
void write(byte[] b)
void write(byte[] b, int off, int len)
すでにデフォルトの実装で実装されています。
javadocはヒントを提供します:
OutputStreamのサブクラスを定義する必要があるアプリケーションは、常に少なくとも1バイトの出力を書き込むメソッドを提供する必要があります。
(つまり、void write(int b) throws IOException
)
実際のコードを見ると、write()
この基本抽象クラスのデフォルトの他のメソッドは、実装する必要のある唯一のメソッドを使用しています。
また、出力ストリームは実際のリソースにリンクされていない場合があります(ByteArrayOutputStream
たとえば)。したがって、このクラスにはデフォルトの実装が.close()
あり.flush()
、何も実行せず、背後に実際のリソースがあるストリームによってのみオーバーライドする必要があります。
テストの目的に関しては、単体テストの唯一の違いは、実際にはでextends
はなく、implements
必要なメソッドをオーバーライドすることを忘れないことです。または、モックライブラリ(mockito、jmockなど)を使用します。
実際、java.io.OutputStream (java.io.InputStream と同じ) はDecorator パターンを使用します。質問に関連して、ここから得られた応答があります ( Head First Design Patterns page 93):
要点は、デコレータが装飾しようとしているオブジェクトと同じタイプを持つことが重要だということです。したがって、ここでは継承を使用して型の一致を実現していますが、動作を取得するために継承を使用していません。
そのため、この場合、インターフェイス (ポリモフィズム) よりも継承 (AbstracClass) を優先します。ただし、他のほとんどの場合、原則は逆であることに注意してください。「継承(抽象クラス)よりも構成(インターフェース)を優先する」。
そのメソッドの1つを除いてすべてが具象(実装)であるため、おそらく抽象クラスです...そして、他の何かが必要なときはいつでも(テスト用に)サブクラス化できます。または、テスト状況によってはモックすることもできます。 。
抽象クラスとして作成されているため、インターフェイスとして扱うことができます。
とはOutputStream
異なりinterface
、クラスはメソッドのデフォルトの実装を提供しますwrite
。