设计Java通用层次结构以避免模板类冲突

时间:2018-07-20 16:18:31

标签: java generics inheritance collections

考虑以下原始类型形式的Java通用类层次结构。

class A ...
class B extends A ...
class C extends A ...

使用A类中的方法,并在B和C中覆盖。

String foo() ...
String bar(A a) ...

我们可以成功拨打以下电话。

String r = (new B()).foo();
String r = (new B()).bar(new C());

这里的真正目标是将A的实例保存在容器中 并处理它们,而不考虑我们拥有哪种A。

A fred;
List as = new LinkedList();
for (A a : as) ... fred.bar(a); ...

可以毫无问题地构造类B和C的对象并将其传递给foo。 现在我们介绍泛型。

class A<T,U,V> ...
class B<T> extends A<T,Void,Object> ...
class C<N> extends A<String,Void,Object> ...

使用A类中的方法,并在B和C中覆盖。

T foo() ...

然后我们进行以下合理调用。

String r = (new A<String,Void,Object>()).foo();
String r = (new B<String>()).foo();
String r = (new C<Integer>()).foo();

String r = (new B<String>()).foo();
String r = (new B<String>()).bar(new C<Integer>());

这里的真正目标是将A的实例保存在容器中 并处理它们,而不考虑我们拥有哪种A。

A<String,String,Integer> fred;
List<A<String,String,Integer>> as = new LinkedList<>();
for (A a : as) ... fred.bar(a); ...

这些决定使得无法将类型B和C的对象加载到“ as”列表中, 由于通用模板中的类型冲突。

请注意,这是我正在尝试清除其警告的现有软件的地方。

1 个答案:

答案 0 :(得分:1)

如果您只关心foo()的返回值,则可以使用以下方法:

List<A<String, ?, ?>> as = ...;

这将使您存储AA的任何子类型,其中T的类型参数为String,但存储UV。所以:

as.add(new A<String, String, Integer>()); // fine
as.add(new B<String>()); // fine
as.add(new C<Integer>()); // fine

as.add(new A<Double, String, Integer>()); // won't compile

但是,您将无法调用参数类型为AU的{​​{1}}方法。如果这是一个问题,那么似乎您必须以某种方式重新设计。

可能还会看到: