ビジター パターンで Java ジェネリックを使用する場合、私はある種の問題を抱えています。
私のコードは次のようなものです:
public interface MyInterfaceVisitor<A, B> {
public A visitMyConcreteObject(MyConcreteObject object, B parameter);
}
public interface MyObject {
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter);
}
public class MyConcreteObject implements MyObject {
@Override
public <A, B> A accept(MyInterfaceVisitor<A, B> visitor, B parameter) {
return visitor.visitMyConcreteObject(this, parameter);
}
}
public class MyConcreteVisitor implements MyInterfaceVisitor<????> {
@Override
public <X extends C> X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
// Do a lot of things.
// Return an instance of the given class.
}
// This method is the entry point of the MyConcreteVisitor.
public <X extends C> void someOtherMethod(Class<X> parameter) {
MyObject m = ...;
X x = m.accept(this, parameter);
...;
}
}
public class C {}
public class Dog extends C {}
public class Cat extends C {}
public class Client {
public static void main(String... args) {
MyConcreteVisitor v = new MyConcreteVisitor();
v.someOtherMethod(Cat.class);
v.someOtherMethod(Dog.class);
}
}
// We have other implementations of the visitor that does not matters, like this one.
public class SomeOtherConcreteVisitor implements MyInterfaceVisitor<String, Integer> {
@Override
public String visitMyConcreteObject(MyConcreteObject object, Integer parameter) {
return "foo";
}
}
???? の一般的な署名を見つける必要があります。これにより、コードがコンパイル可能になり、MyConcreteVisitor クラスのオーバーライドされたメソッドが MyInterfaceVisitor インターフェイスのシグネチャと一致するようになります。
MyInterfaceVisitor インターフェイスの visitMyObject の署名も、そのジェネリックも変更できません。これは、MyInterfaceVisitor の他の実装が存在し、それらのジェネリックが MyConcreteVisitor のジェネリックとは何の関係もないために発生します。
MyConcreteVisitor クラスにはジェネリック自体があってはならないため、コンパイラはMyConcreteVisitor v = new MyConcreteVisitor();
unchecked または rawtypes 警告を生成せずに a を許可する必要があります。
具体的な visitMyObject を変更public C visitMyObject(MyObject object, Class<? extends C> parameter)
して ???? を宣言すると as として<C, Class<? extends C>>
、someOtherMethod にキャストを追加する必要があります。
unchecked または rawtypes の警告を受けたり、インターフェイスを変更したり、キャストを追加したりせずに、ジェネリック型を定義してコンパイル可能にする方法は? これはJavaでも可能ですか、それともジェネリックを乱用しすぎていますか?