作成中のプログラムで、インターフェースに関する問題が発生しました。メソッドの 1 つが自身のオブジェクトの型への参照を受け取ったり返したりするインターフェースを作成したいと考えています。次のような内容です。
public interface I {
? getSelf();
}
public class A implements I {
A getSelf() {
return this;
}
}
public class B implements I {
B getSelf() {
return this;
}
}
「?」の代わりに「I」を使うことはできません。インターフェースへの参照ではなく、クラスへの参照を返したいからです。調べたところ、Java には「自己参照」する方法がないので、例の「?」を「self」キーワードなどに置き換えることはできません。実際、次のような解決策にたどり着きました。
public interface I<SELF> {
SELF getSelf();
}
public class A implements I<A> {
A getSelf() {
return this;
}
}
public class B implements I<B> {
B getSelf() {
return this;
}
}
しかし、それは本当に回避策かそれに似たもののように思えます。別の方法はありますか?
ベストアンサー1
インターフェースを拡張するときに、独自のクラスをパラメーターとして使用するように強制する方法があります。
interface I<SELF extends I<SELF>> {
SELF getSelf();
}
class A implements I<A> {
A getSelf() {
return this;
}
}
class B implements I<A> { // illegal: Bound mismatch
A getSelf() {
return this;
}
}
これはジェネリック クラスを記述するときにも機能します。唯一の欠点は、
this
に キャストする必要があることです
SELF
。
アンドレイ・マカロフが指摘したように下のコメントこれはないジェネリッククラスを記述するときに確実に動作します。
class A<SELF extends A<SELF>> {
SELF getSelf() {
return (SELF)this;
}
}
class C extends A<B> {} // Does not fail.
// C myC = new C();
// B myB = myC.getSelf(); // <-- ClassCastException