2

所以我得到了一个接口SuperType和一堆实现类TypeATypeB等等。我还有一个具有参数化方法的顶级接口:

public interface UsedByProductThing<T extends SuperType> {
    public T doStuff(T one);
}

我有一个工厂(见下文)生产对象实现GeneralProduct

public interface GeneralProduct<T extends SuperType> {
    T doSomething(T input);
}

这是实施ProductA

public class ProductA implements GeneralProduct<TypeA> {
    UsedByProductThing<TypeA> in;

    public ProductA(UsedByProductThing<TypeA> in) {
        this.in = in;
        in.doStuff(new TypeA());
    }

    @Override
    public TypeA doSomething(TypeA input) {
        return null;
    }
}

现在有问题的工厂:

public class GeneralFactory {
    public static <T extends SuperType> GeneralProduct<T> createProduct(
            int type, UsedByProductThing<T> in) {
        switch (type) {
        case 1:
            return (GeneralProduct<T>) new ProductA((UsedByProductThing<TypeA>) in);
            // at this point, i want to return a "new ProductA(in)" preferably
            // without casting
            // or at least without the cast of the argument.
        default:
            throw new IllegalArgumentException("type unkown.");
        }
    }
}

正如评论的那样,我希望工厂方法不使用演员表。我知道返回类型必须是 GeneralProduct,但我想不出一种省略演员表的方法(它也给了我一个“未经检查的演员表”警告)。另外,我想不出一种省略论点的方法。如果有必要摆脱那个地方的“不安全”铸造,我可以重组整个代码。你能告诉我一个在这里又好又顺利的方法吗?

另外,请根据需要编辑我的问题-我不知道如何在标题中正确解决该问题。

非常感谢!

4

3 回答 3

4

你不能避免铸造,因为

  • 你有in哪个类型UsedByProductThing<T>你想变成 aUsedByProductThing<TypeA>并且编译器无法知道那TTypeA
  • ProductA 是GeneralProduct<TypeA>并且编译器也不知道它T是 a TypeAhere。

避免强制转换的唯一方法是替换TTypeA

    public static GeneralProduct<TypeA> createProduct(
            int type, UsedByProductThing<TypeA> in) {
        switch (type) {
            case 1:
                return new ProductA(in);
            default:
                throw new IllegalArgumentException("type unkown.");
        }
    }
于 2012-09-14T12:31:45.377 回答
0

我不确定有什么干净的方法可以做到这一点。另外,我认为任何铸造方式无论如何都是不安全的,因为有人可能传递与“in”值不兼容的“type”值。

话虽如此,在处理泛型时,这些固有的未经检查的强制转换很常见。如果可能的话,你应该避免它们,但有时你不能,如果你真的只是想摆脱编译器警告,你应该添加注释来抑制。

@Suppress("未选中")

或者,为什么不采取建设者的方法呢?

public inteface Builder<T extends SuperType> {
    public GeneralProduct<T> createProduct(UsedByProductThing<T> thing);
}

public class BuilderFactory {
    public static <T extends SuperType> Builder<T> createBuilder(Class<T> clazz) {
       if (clazz.equals(ProductA.class)) {
          return new (Builder<T>) ProductABuilder();
       }
       ...
    }
}

然后就这样使用它(假设您已经创建了一个构建器impl:

Builder<ProductA> builder = BuilderFactory.createBuilder(ProductA.class);
UsedByProductThing<ProductA> thing = ...;
ProductA product = builder.createProduct(thing);
于 2012-09-14T12:39:50.013 回答
0

不回来

"GeneralProduct<T>"

,你最好回来

"GeneralProduct<?>"

,所以不需要转换结果。

但无论如何,您必须为“ProductA”转换参数!

于 2012-09-14T12:45:11.587 回答