基本クラスが再帰的な自己型を定義するクラス階層があるとします。
abstract class A<T extends A<T>> { }
A の任意のサブクラスを保持できるフィールドを使用して、別のクラス (T はオブジェクトの存続期間にわたって変化する可能性があるため、T ではジェネリックであってはなりません) を宣言するにはどうすればよいですか?
以下は機能しません。
public class B {
//fails to compile, because the capture of ? is not sufficiently narrow
private A<?> a;
public <T extends A<T>> setA(T a) {
this.a = a;
}
}
-- 質問の終わり --
多くの StackOverflow メンバーが、特定の難しい質問に「そもそもなぜそんなことをしているのですか?」とアプローチする傾向があることに気付きました。以下は、このパターンの使用を正当化するものです。Java 標準ライブラリでは、Enum クラスの定義で再帰的な自己型も使用されていることに注意してくださいEnum<E extends Enum<E>>
。この質問は、「 type のフィールドを定義する方法」と同様に尋ねることができますEnum<?>
。
正当化の例:
abstract class A<T extends A<T>> {
public abtract T self();
public B<T> bify(Bifyer bifyer) {
return bifyer.bify(self());
}
}
サブクラスで:
class ASub1 extends A<ASub1> {
public ASub1 self() { return this; }
}
class ASub2 extends A<ASub2> {
public ASub2 self() { return this; }
}
並列クラス階層にバインド:
abstract class B<T extends A<T>> {
}
class BSub1<T extends A<T>> implements B<T> { }
class BSub2<T extends A<T>> implements B<T> { }
//and others
Bifyer インターフェイスの実装によって管理される B インスタンスの生成:
interface Bifyer {
B<ASub1> bify(ASub1 asub1);
B<ASub2> bify(ASub2 asub2);
}
このインターフェイスの実装は、B に対して BSub1 または BSub2 を返す場合があります。これは基本的に、Bifyer がビジターである Visitor パターンのアプリケーションですが、標準の Visitor とは異なり、accept メソッドは void ではなく値を返します。これにより、さまざまな Bifyer 実装を指定して、Bify メソッドの代替動作と戻り値の型 (たとえば、B のサブクラスごとに 1 つ) を提供できるモジュラー フレームワークが提供されます。