java - 设计 Java 通用层次结构以避免模板类冲突
问题描述
考虑以下 rawtype 形式的 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”列表中。
请注意,这是我试图清除警告的现有软件的地方性。
解决方案
如果你只关心 的返回值foo()
,那么你可以使用这个:
List<A<String, ?, ?>> as = ...;
这将允许您存储类型参数为is的A
任何子类型,但使用and的任何内容。所以:A
T
String
U
V
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
但是,您将无法调用A
其参数类型为U
和的方法V
。如果这是一个问题,那么您似乎必须以某种方式重新设计。
可能还看到:
推荐阅读
- debugging - VS Code APEX CLI 测试方法调试
- javascript - Javascript 我可以将 const 转换为输出功能吗
- r - 箱线图:Matlab 显示关于 R 的不同图形?
- winapi - 如何监控和记录可执行文件对某些操作的 Win API 调用?
- javascript - Fullcalendar 使用变量添加事件
- r - 对于空间中的特定点,获取该点所在的像素(在 R 中)
- podio - Podio API:未附加的文件保留多长时间?
- php - 即使我在错误上运行 exit(),我的 PHP 代码也会返回 true
- javascript - 包括来自外部文件的嵌入式 javascript 函数
- c# - Process.Start 以“每个人”的用户名开始?