具有子类泛型的子类
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
在库中并且您无法修改它,因此无法干净地处理这种情况,即如您所料。
因为 Parent1Container
和 Parent2Container
不完全是 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 那么这两个集合是等价的。
如果您的案例 ?
可以是 Parent1Object
或 Parent2Object
,那么您只能将其保留为 ?
。
我对泛型有一些疑问。我有一个 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>
norList<Integer>
is asubtype
of the other, even thoughInteger
is a subtype ofNumber
. So, any method that takesList<Number>
as a parameter does not accept an argument ofList<Integer>
. If it did, it would be possible to insert aNumber
that is not anInteger
into it, which violates type safety.
由于 BaseClass
在库中并且您无法修改它,因此无法干净地处理这种情况,即如您所料。
因为 Parent1Container
和 Parent2Container
不完全是 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 那么这两个集合是等价的。
如果您的案例 ?
可以是 Parent1Object
或 Parent2Object
,那么您只能将其保留为 ?
。