したがって、インターフェイスへのコーディング (具体的な型ではなく変数の宣言型としてインターフェイスを使用する) は、さまざまな理由から、オブジェクト指向コードでの優れた方法であることを知っています。これは、Java コレクションなどでよく見られます。では、そのインターフェイスの特定の実装のみが正しい動作を提供する場合でも、プログラム内のインターフェイスを参照することは良いことでしょうか?
たとえば、Java プログラムがあります。そのプログラムには、複数のオブジェクトのセットがあります。要素を重複させたくないので、セットを使用することにしました。ただし、リストの順序付けプロパティ (つまり、挿入順序を維持する) が必要でした。したがって、具体的な Set 型として LinkedHashSet を使用しています。これらのセットが使用されることの 1 つは、次のように、セットに含まれるオブジェクトのプリミティブ フィールドを含む内積を計算することです (少し単純化します)。
double dot(LinkedHashSet<E> set, double[] array) {
double sum = 0.0;
int i = 0;
for(E element : set) {
sum += (element.getValue()*array[i]);
}
return sum;
}
このメソッドの結果は、セットの反復順序に依存するため、特定の Set 実装 (主に HashSet) では、正しくない/予期しない結果が返されます。現在、正しい動作を保証するために、Set ではなく、宣言された型としてプログラム全体で LinkedHashSet を使用しています。しかし、それはスタイル的に悪い感じです。ここで何をするのが正しいですか?この場合、具象型でいいのでしょうか?または、タイプとして Set を使用する必要がありますが、どの実装が正しい動作を生成するかしないかをドキュメントに記載する必要がありますか? 上記のシナリオに固有のものよりも、一般的な情報を探しています。特に、これは、LinkedHashSet または TreeSet の順序付けプロパティを使用している実際のすべてのシナリオに適用されます。意図しない実装が使用されるのをどのように防ぎますか? (インターフェイスを捨てることによって) コードでそれを強制しますか、それともドキュメントで指定しますか? それとも他のアプローチですか?