具有子类泛型的子类

Subclasses with generics of subclasses

我对泛型有一些疑问。我有一个 BaseObject 和多个 sub-类 以及一个 BaseContainer<T extends BaseObject> 和 sub-类 对应于 BaseObject sub-类。

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();
}

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


我试过向容器实例化添加强制转换,但它留下了丑陋的未经检查的警告,让我觉得我只是错过了一些东西。我想避免这些并抑制警告。

如果可能,我如何重写 类 中的任何一个以使 createContainer() 方法起作用?

写成 here

Neither List<Number> nor List<Integer> is a subtype of the other, even though Integer is a subtype of Number. So, any method that takes List<Number> as a parameter does not accept an argument of List<Integer>. If it did, it would be possible to insert a Number that is not an Integer into it, which violates type safety.

由于 BaseClass 在库中并且您无法修改它,因此无法干净地处理这种情况,即如您所料。

因为 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> 引用所有那些能够 "handle" 任何 BaseObject 的 BaseContainer(包括扩展 classes)实例,其中 handle 是所有操作的总称它可能与该类型参数有关。

相比之下,BaseContainer<? extends BaseObject> 指的是那些旨在处理所有 BaseObject 的子集的 BaseContainer 实例,其中顶级父 class 未知(因此 ?)。如果 ? 恰好是 BaseObject 那么这两个集合是等价的。

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