2

私の前の質問のフォローアップとして、次のよう な一般的な境界を組み合わせた関数を持つ:

<T extends Foo & Bar> void doStuff(T argument) {
  //do stuff wich should only be done if arguments is both foo and bar
}

これは未指定のオブジェクトからキャストできないため、これらのインターフェイスを実際に実装するオブジェクトについての知識が必要です。渡すオブジェクト引数の特定のタイプを知る必要がdoStuff(T a)あることは、デメテルの法則に違反しているように思えます。

この関数は、実際のクラスを知る必要性を指定していません (さまざまなクラスが存在する可能性があります)。このクラスを知ると、コード ベースの依存関係が増加するため、知りたくありません。

これらの境界を使用するのはアンチ パターンですか? もしそうなら、どのようにそれを避けるべきですか?

ケース シナリオには、オブジェクトが永続的であることを指定する 1 つのインターフェイスと、関連するエンティティを持つ別の指定されたオブジェクトが含まれます。この場合のdoStuff(T a)関数は、永続化されたときに関連エンティティを永続化しました。ただし、非永続エンティティも関連エンティティを持つことができますが、doStuff(T a)関数によって処理されるべきではありません

4

3 に答える 3

4

組み合わせた一般的な境界をアンチパターンとは見なしません。少なくとも、私のコードではそれらをいくつか使用しています。たとえば、次のサンプル コードは、Comparable インターフェイスから compareTo を使用して、コレクション内の最大の Number インスタンスを見つけます。

<T extends Number & Comparable<T>> T max(Collection<T> numbers)
于 2008-11-26T10:39:27.127 に答える
2

doStuff(T a) に渡すオブジェクト引数の特定のタイプを知る必要があることは、デメテルの法則に違反しているように思えます

同意しません。方法がわからない

T<? extends Foo & Bar> void doStuff(T argument) 

その場合、引数を渡すにはこれ以上の知識が必要です

T<? extends Foo> void doStuff(T argument) 

またはそれ以上

void doStuff(T argument) 

すべての場合において、引数について何かを知る必要があります。最初のケースでは、2 つの識別子があるため、他のケースよりも多くの知識が必要になるとは思いません。

于 2008-11-26T11:06:08.413 に答える
0

アンチパターンはキャストです。

ただし、派手なジェネリックスのフットワークは、上級でないプログラマーにとっては混乱を招く可能性があります。そのようなタイプとメソッドの使用は、それらの実装よりもはるかに簡単なはずです。

于 2008-11-26T11:19:13.053 に答える