web-dev-qa-db-ja.com

Javaコレクションがインターフェースの「オプションのメソッド」で実装されたのはなぜですか?

Javaコレクションフレームワークを拡張する最初の実装中に、コレクションインターフェースにオプションとして宣言されたメソッドが含まれているのを見て、私はかなり驚いていました。サポートされていない場合、実装者はUnsupportedOperationExceptionsをスローすることが期待されています。これはすぐに私を襲った不十分なAPI設計の選択。

Joshua Blochの優れた「Effective Java」の本の多くを読んだ後、彼がこれらの決定に責任があるかもしれないことを学んだ後、それは本で支持されている原則に固執していないようでした。 Collectionと、「オプションの」メソッドでCollectionを拡張するMutableCollectionの2つのインターフェイスを宣言すると、クライアントコードがはるかに保守しやすくなると思います。

問題の優れた要約 here があります。

2つのインターフェースの実装の代わりにオプションのメソッドが選択された正当な理由はありましたか?

69
glenviewjeff

[〜#〜] faq [〜#〜] が答えを提供します。要するに、実装されたオプションメソッドの可能なセットごとに、変更可能、変更不可のビュー、削除のみ、追加のみ、固定長、不変(スレッド化のため)などの必要なインターフェースの潜在的な組み合わせの爆発を見ました。

28
ratchet freak

Interface Segregation Principleは当時ほど探求されていなかったように思えます。その方法(つまり、インターフェイスにはすべての可能な操作が含まれ、不要なものに対して例外をスローする「縮退」メソッドがあります)は、SOLIDおよび品質コードの事実上の標準。

10
Wayne Molina

「オプションのメソッド」を嫌う人もいますが、多くの場合、高度に分離されたインターフェースよりも優れたセマンティクスを提供します。特に、オブジェクトはその存続期間中に能力または特性を獲得する可能性、またはオブジェクト(特にラッパーオブジェクト)が構築されるときに、正確な能力を報告する必要があることを認識できない可能性を考慮に入れます。

Javaコレクションクラスパラゴンを優れたデザインのパラゴンと呼ぶことはほとんどありませんが、優れたコレクションフレームワークには、その基礎に多数のオプションメソッドを含めることをお勧めしますコレクションの特性と能力について尋ねる。このような設計により、単一のラッパークラスを多種多様なコレクションで使用できるようになり、基になるコレクションが持つ可能性のある機能を誤って不明瞭にすることがなくなります。メソッドがオプションでない場合は、コレクションがサポートする可能性のある機能の組み合わせごとに異なるラッパークラスを用意する必要があります。そうでない場合、状況によっては一部のラッパーが使用できなくなります。

たとえば、コレクションがインデックスによるアイテムの書き込みまたは末尾へのアイテムの追加をサポートしているが、途中でのアイテムの挿入はサポートしていない場合、コレクションで実行されるすべてのアクションをログに記録するラッパーにそれをカプセル化するコードには、バージョンが必要です。サポートされる機能の正確な組み合わせを提供するロギングラッパーの使用、または使用可能な機能がない場合は、appendまたはwrite-by-indexのいずれかをサポートするが両方をサポートしないラッパーを使用する必要があります。ただし、統合コレクションインターフェースが3つのメソッドすべてを「オプション」として提供したが、どのオプションメソッドが使用可能かを示すメソッドが含まれている場合、単一のラッパークラスが、機能の任意の組み合わせを実装するコレクションを処理できます。ラッパーがサポートする機能を尋ねられると、ラッパーはカプセル化されたコレクションがサポートするものは何でも報告することができます。

「オプション機能」の存在により、場合によっては、集約されたコレクションが特定の機能を実装できるようになることがあります。これは、実装の存在によって機能が定義された場合よりもはるかに効率的な方法で機能を実装できるためです。たとえば、concatenateメソッドを使用して他の2つの複合コレクションを形成したとします。最初のコレクションはたまたま1,000,000要素のArrayListで、最後は20要素のコレクションで、最初から繰り返されます。複合コレクションが1,000,013番目の要素(インデックス1,000,012)を要求された場合、ArrayListに含まれるアイテムの数(つまり1,000,000)を要求し、要求されたインデックスからそれを差し引いて(12を生成)、2番目の要素から12個の要素を読み取ってスキップできます。コレクション、次の要素を返します。

このような状況では、コンポジットコレクションにインデックスでアイテムを返す瞬時の方法がない場合でも、1,000,013番目のアイテムをコンポジットコレクションに要求すると、1,000,013アイテムを個別に読み取って最後のアイテム以外をすべて無視するよりもはるかに高速になります。 1。

4
supercat