あなたが実際にあなたが生の型を使用することにより破る相互再帰的な一般的な定義を持っている:
b.setA((A)this); // <- Unchecked cast
this
には、タイプInterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA>>
のですが、それはタイプInterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA<? extends InterfaceA.InterfaceB<...>>>>
でなければなりません。代わりに
public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {
public interface InterfaceB<A extends InterfaceA<B>> { //<- cannot make a static reference to the non-static type B
void setA(A a);
}
}
を使用する必要がありますが、あなたは(インターフェイス宣言は常に静的です)静的インタフェース宣言で、非静的である、B
を使用することはできません。
詳細については
、一つのさらなる挑戦:今interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>>
でInterfaceA
のネストされた型パラメータは再びInterfaceA.InterfaceB<?>
の任意のサブクラスであるため、
代替
public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {
public interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>> {
void setA(A a);
}
}
abstract class AImplTwo<B extends InterfaceA.InterfaceB<A>, A extends InterfaceA<B>> implements InterfaceA<B> {
private final B b;
public AImplTwo(B b) {
this.b = b;
b.setA((A)this); // <-- Unchecked cast
}
}
を使用するには、再度、未チェックのキャストが発生します。
更新、あなたは一般的な設計のために求めてきましたので、:
私は具体的な実装から抽象化としてInterfaceB(一般的には実際には、インタフェース)を思うだろう:あなただけのインターフェイスInterfaceBを必要とし、 InterfaceAの実装では実装の詳細ではありません。 InterfaceBは契約のようなものであり、実装については気にしません。したがってInterfaceBの実装にInterfaceAの実装を結合するための必要はありません。
public interface InterfaceA {
public interface InterfaceB {
void setA(InterfaceA a);
}
}
私が見ることができない理由のために、あなたはそのInterfaceBのすべてのインスタンスに対して同じ型を持つようにしたいんのみ、場合ジェネリックが必要です。逆もまた同様です。上記の最後のジェネリックの例では、少なくともInterfaceAとInterfaceBの型を修正することができ、AのBとBのAが同じであることを動的に宣言するだけで済みます。全くタイプがチェックソリューションは、Javaに存在しないことを示す
は難しいですが、多分それはJavaが延びており、スーパーの組み合わせを許可されている場合は解決策になる次の例でもっともらしくなった:
public interface A<TB extends A.B<?>> {
public interface B<TA extends A<? extends A.B<?>>> {
void setA(TA a);
}
}
class AImplTwo<TB extends A.B<TA>, TA extends AImplTwo<TB, TA> super AImplTwo<TB, TA>> implements A<TB> {
private final TB b;
public AImplTwo(TB b) {
this.b = b;
b.setA((TA)this);
}
}
.. 。それを考えようとすると、プラグイン可能なタイプのシステムはJavaにさらにタイピングを追加し、この拡張とスーパーの組み合わせを可能にし、したがってあなたの問題に対する解決策を提供するかもしれません。しかし、私はそれがあなたが得るもののためにはあまりにも複雑であることを知り、ジェネリックスなしでインターフェイスを使用するか、チェックされていないキャストを使用するだけです。
ジェネリックに関する質問で1文字のクラス名「A」を使用すると、非常に混乱します – artbristol
ネストされたクラスを使用するだけでなく、AImplはAImplOneまたはAImplTwoでなければなりません。質問名にはタイプミスがあります'B *>'の型パラメータがありません。問題があるかもしれませんが、サンプルコードが少し複雑すぎます。 –
rlegendi
@artbristol:Good Point: 「InterfaceA」に「A」、「InterfaceB」に「B」を変更しました – Peter