4

在访问者模式中使用 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 类本身不应具有泛型,因此编译器必须允许 aMyConcreteVisitor v = new MyConcreteVisitor();而不会生成 unchecked 或 rawtypes 警告。

如果我将具体的 visitMyObject 更改为public C visitMyObject(MyObject object, Class<? extends C> parameter)并声明 ???? 因为<C, Class<? extends C>>,我需要在 someOtherMethod 中添加一个演员表。

如何定义泛型类型使其可编译,而不会收到未经检查或 rawtypes 警告、更改接口或添加强制转换?这在java中是否可能,或者我滥用泛型太多了?

4

2 回答 2

2

问题是您的实现正试图向X extends C方法引入另一个类型参数visitMyConcreteObject并用它解析B参数。您不能使用visitMyConcreteObject泛型,X而是尝试B使用由参数化的类型解析X,例如Class<X>,因为B在类声明中解析但X仅由类的方法声明。

据我所知,你有两个选择。要么MyConcreteVisitor通用X

public class MyConcreteVisitor<X extends C> implements MyInterfaceVisitor<X, Class<X>> {

    @Override
    public X visitMyConcreteObject(MyConcreteObject object, Class<X> parameter) {
        // Do a lot of things.
        // Return an instance of the given class.
    }
}

或者摆脱X并失去类型安全(超出具体类型C):

public class MyConcreteVisitor implements MyInterfaceVisitor<C, Class<? extends C>> {

    @Override
    public C visitMyConcreteObject(MyConcreteObject object, Class<? extends C> parameter) {
        // Do a lot of things.
        // Return an instance of the given class.
    }
}
于 2013-01-28T16:19:50.703 回答
1

我认为这就是您要寻找的东西:

public class MyConcreteVisitor implements MyInterfaceVisitor<Object,Class<?>> {

    @Override
    public Object visitMyConcreteObject(MyConcreteObject object, Class<?> parameter) {
        // Do a lot of things.
        // Return an instance of the given class.
    }

    // This method is the entry point of the MyConcreteVisitor.
    public <X> void someOtherMethod(Class<X> parameter) {
        MyObject m = ...;
        X x = parameter.cast(m.accept(this, parameter));
        ...;
    }
}
于 2013-01-28T16:14:03.550 回答