具有子类泛型的子类

时间:2017-03-31 18:36:45

标签: java generics subclass

我在泛型方面存在一些问题。我有一个带有多个子类的BaseObject以及一个带有与BaseContainer<T extends BaseObject>子类对应的子类的BaseObject

public class TestClass extends BaseClass<BaseContainer<BaseObject>> {

    // method signature tied to BaseClass generic
    @Override
    private BaseContainer<BaseObject> createContainer() {
        BaseContainer<BaseObject> container;

        // example logic here to determine which container to use
        if (Math.random() < 0.5) {
            container = new Parent1Container(); // incompatible types
        } else {
            container = new Parent2Container(); // incompatible types
        }

        return container;
    }

    abstract static class BaseObject {}
    static class Parent1Object extends BaseObject {}
    static class Parent2Object extends BaseObject {}

    abstract static class BaseContainer<T extends BaseObject> {
        public abstract void foo(T object);
    }
    static class Parent1Container extends BaseContainer<Parent1Object> {
        public void foo(Parent1Object object) {}
    }
    static class Parent2Container extends BaseContainer<Parent2Object> {
        public void foo(Parent2Object object) {}
    }

}
public class BaseClass<T extends BaseContainer> {
    public abstract T createContainer();
}

我有一个返回BaseContainer<BaseObject>的方法。不幸的是,实例化BaseContainer的子类会导致类型不兼容错误。

我已经尝试将强制转换添加到容器实例化中,但它留下了丑陋的未经检查的警告,这让我觉得我只是缺少某些东西。我想避免这些并禁止警告。

如果可能,我如何重新编写任何类以使createContainer()方法有效?

2 个答案:

答案 0 :(得分:1)

正如here所写,

  

List<Number>List<Integer>都不是另一个的subtype,即使IntegerNumber的子类型。因此,任何以List<Number>作为参数的方法都不接受List<Integer>的参数。如果有,则可以在其中插入Number Integer,这违反了类型安全。

由于BaseClass位于库中而您无法对其进行修改,因此无法正常处理此情况,即按预期进行处理。

答案 1 :(得分:1)

由于Parent1ContainerParent2Container不完全是BaseContainer<BaseObject>BaseContainer<? extends BaseObject> 你需要相应地改变签名:

public class TestClass extends BaseClass<BaseContainer<? extends BaseObject>> {
    ...
    public BaseContainer<? extends BaseObject> createConstructor() {
        if (Math.random() < 0.5) {
           return new Parent1Container();
        } else {
           return new Parent2Container();
        }
    }
    ...
}

BaseContainer<BaseObject>引用了所有能够“处理”任何BaseObject的BaseContainer(包括扩展类)实例,其中handle是它可以对该类型参数执行的所有操作的毯子术语。

相反,BaseContainer<? extends BaseObject>指的是那些旨在处理顶级父类未知的所有BaseObject子集的BaseContainer实例(因此?)。它?碰巧是BaseObject,那么这两个集合就是等价的。

如果您的案例?可以是Parent1ObjectParent2Object,那么您只能将其保留为?