2

オブジェクト ベースのコレクションがジェネリフィケーションの最有力候補であり、コレクション ライブラリで既にジェネリフィケーションされていることを私は知っています。それ以外に、クラスまたはインターフェースがジェネリフィケーションの候補にするために、どのような属性と動作を保持する必要がありますか? たとえば、 ThreadLocalクラスまたはAtomicReferenceクラスが一般化されたのはなぜですか? この設計上の決定に至った理由は何ですか?

4

5 に答える 5

3

異なる型に再利用する必要があるクラスは、常にジェネリフィケーションの候補です。例えばclass Pair<U,V>

于 2013-02-20T18:37:50.623 に答える
3

クラスが他のさまざまなクラスと同じ関係を持つことができる場合、そのクラスはジェネリフィケーションの良い候補です。コレクション クラスが生成されるのは、「含む」という関係がオブジェクトのどのクラスにも適用できるためです。「と比較できる」という関係は多くの異なるオブジェクトに適用できるため、Comparableおよびインターフェイスは汎用的です (ただし、実際には、これは のクラス独自の階層内およびその周辺のオブジェクトに限定されます)。ComparatorComparable

さらに、非常によく似た複数のクラスを作成していて、唯一の違いが操作対象のオブジェクトのタイプであることに気付いた場合は、1 つの汎用クラスを作成することを検討してください。

編集:

組み込みクラスAtomicReferenceおよびを使用するとThreadLocal、「含む」関係がさまざまなオブジェクト タイプに適用されます。AtomicReferenceおよびオブジェクトには、まだ別のタイプのThreadLocalオブジェクトが含まれています。これにより、特定の型をタイプ セーフな方法で設定および返すことができます。「get」および「set」メソッドが戻り値を取得する必要はなく、「get」をObject呼び出すときに戻り値の型をキャストする必要がなくなります。 " 方法。この関係は特定の型に適用されますが、クラスの設計時に正確な型を知る必要はありません。

編集2:

クラスをジェネリックにするために考えられるほとんどの例には、「含む」関係が含まれます。ただし、コレクション フレームワークは "contains" 関係に基づいており、"contains" で生成されたクラスを多数提供していますが、これは一般的な関係の 1 つの具体例にすぎません。一般的な関係は「含む」必要はないので、何かを一般化できるが関係が「含む」場合の例を挙げようとします。

、、Shapeなどの具体的なクラスを持つ抽象クラスを想像してみてください。次に、形状を描画する方法を知っているインターフェイスを定義します。ここでの関係は「ドロー」です。インターフェイスを次のように定義できます。LineSquareCircleShapeDrawer

public interface ShapeDrawer {
   public void drawShape(Shape shape);
}

ここで、や などShapeDrawerの特定の形状に特化したの具体的な実装が必要です。CircleDrawerSquareDrawer

public class CircleDrawer implements ShapeDrawer {
   public void drawShape(Shape shape) {/*...*/}
}

drawShapeメソッドは、描画する前にそれが であるかどうかをCircleDrawerテストする必要があります。shapeCircle

さて、ジェネリックを使用したソリューション:

public interface ShapeDrawer<T extends Shape> {
   public void drawShape(T shape);
}

これで、実装は特定の を描画できますShape:

public class CircleDrawer implements ShapeDrawer<Circle> {
    public void drawShape(Circle circle) {/*...*/}
}
于 2013-02-20T18:38:03.747 に答える
1

構造は複数のタイプの入力を処理できる必要があるため、データ構造は汎用的である必要があります。

複数のデータ型で使用できる/使用する必要があるクラスは、一般的な方法で作成する必要があります。

于 2013-02-20T18:38:58.940 に答える
1

「一般化」するものを探してはいけません。むしろ、ジェネリックを使用して、最適と思われる方法で特定のタスクを達成する必要があります。Generics は、タスクを実行するためのツールボックス内の単なるツールです。

あなたの質問が、おそらく一般的にどのようなものが最もよく実装されているかということであれば、あなた自身の例は最高のものです。ジェネリックは、リストのように異なる構造を同様の方法で処理する必要がある場合に適したソリューションです。これには、クラス不変の方法で他のクラスを処理する、またはクラスのサブセクションに対して不変であるほとんどのクラスが含まれます。

于 2013-02-20T18:39:18.927 に答える
1

値をキャストしていることに気付いたときはいつでも、ジェネリフィケーションによってそのキャストを削除できるかどうかを検討する必要があります。ThreadLocalあなたの例を見てみましょうAtomicReference. によって返された値を使用する場合はどちらもget()キャストが必要です (少なくともほとんどの場合)。

ジェネリックは非常にうるさい場合があることに注意してください。コストとメリットを天秤にかけてください。特に、ジェネリフィケーションが API ユーザーに利益をもたらすのか、それとも実装者だけに利益をもたらすのかを検討してください。

于 2013-02-20T19:48:53.033 に答える