Fee*_*ard 10 java generics inheritance
假设我有简单的课程
public class MyObject {
}
Run Code Online (Sandbox Code Playgroud)
以及处理MyObject子类的处理程序接口
public interface MyObjectHandler<V extends MyObject>{
List<V> handle(List<V> objects);
}
Run Code Online (Sandbox Code Playgroud)
假设,我有BigObjects和SmallObjects(它们都扩展了MyObject),我想为它们分别设置处理程序.因此,我使用特定的泛型创建MyObjectHandler的两个接口.
class BigObject extends MyObject {}
class SmallObject extends MyObject {}
// Handlers interfaces
interface BigObjectHandler extends MyObjectHandler<BigObject>{}
interface SmallObjectHandler extends MyObjectHandler<SmallObject>{}
// Concrete handlers
class BigHandler1 implements BigObjectHandler {....}
class BigHandler2 implements BigObjectHandler {....}
class SmallHandler1 implements SmallObjectHandler {....}
class SmallHandler2 implements SmallObjectHandler {....}
Run Code Online (Sandbox Code Playgroud)
现在让我们假设我们已经创建了AbstractHandlerChain<...>
抽象类.因此,我们可以创建BigHandlerChain类并注入我们的BigHandlers(和SmallHandlerChain一样).
class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler> {
// Inject only childs of BigObjectHandler. E.g. via spring @Autowired
public BigHandlerChain(List<BigObjectHandler> handlers) {
this.handlers = handlers;
}
}
Run Code Online (Sandbox Code Playgroud)
问题:是否可以为此案例创建完美的AbstractHandlerChain?
public abstract class HandlerChain<T extends MyObjectHandler> {
private List<T> handlers;
public HandlerChain(List<T> handlers) {
this.handlers = handlers;
}
public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
Run Code Online (Sandbox Code Playgroud)
这个可以工作,但是在handler.handle(objects)
我得到的时候Unchecked call to 'handle(List<V>)' as a member of raw type 'MyObjectHandler'
,我应该补充@SuppressWarnings("unchecked")
说这不是很好.
public abstract class HandlerChain<T extends MyObjectHandler<? extends MyObject>> {
...
public <V extends MyObject> List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
Run Code Online (Sandbox Code Playgroud)
不行.在handler.handle(objects)
我得到handle (java.util.List<capture<? extends MyObject>>) cannot be applied to (java.util.List<V>)
.为什么在这种情况下我无法将对象传递给处理程序?通配符扩展MyObject,V扩展MyObject.不是吗?
public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
Run Code Online (Sandbox Code Playgroud)
这个可行,但在这种情况下我应该将BigHandlerChain定义为class BigHandlerChain extends AbstractHandlerChain<BigObjectHandler, BigObject>
.但是BigObjectHandler
已经包含了可以由它处理的类的信息,因此它是信息重复.
public abstract class HandlerChain<T extends MyObjectHandler<V extends MyObject>> {
...
public List<V> doChain(List<V> objects) {
for (T handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个解决方案,我期望从java,但它不起作用!我不能像这样申报课程...class HandlerChain<T extends MyObjectHandler<V extends MyObject>
.为什么我可以在MyObjectHandler之后使用通配符,但是不能使用这种结构?
解决方案1
这个有效,但是在 handler.handle(objects) 中,我得到对“handle(List)”的未经检查的调用,作为原始类型“MyObjectHandler”的成员,所以我应该添加@SuppressWarnings(“unchecked”),这不是很好。
事实上,becauseMyObjectHandler
是一个泛型类型,但您没有在HandlerChain
的类型参数中指定它的类型。
解决方案2
不起作用。在 handler.handle(objects) 中,我得到句柄 (java.util.List>) 无法应用于 (java.util.List)。为什么在这种情况下我无法将对象传递给处理程序?通配符扩展了 MyObject,V 扩展了 MyObject。还不够吗?
没有。? extends MyObject
基本上说它是针对某些未指定的类型扩展的MyObject
,但你没有说是哪个。您可以创建一个类,但向 提供实例public class BigHandlerChain<BigObjectHandler>
列表。SmallObject
doChain
解决方案3
这个可行,但在这种情况下,我应该将 BigHandlerChain 定义为类 BigHandlerChain 扩展 AbstractHandlerChain。但是BigObjectHandler已经包含了它可以处理的类的信息,所以这是信息重复。
事实上,这里有一些重复的信息,但是当像这样组合泛型类型时,很可能会发生这种情况。由于您的doChain
方法对某种类型进行操作,因此必须指定该类型可以做什么。可以将其视为您想要处理BigObject
列表,并且您提供的处理程序必须能够处理 BigObject。
解决方案4
这是我期望从java获得的解决方案,但它不起作用!我无法声明像这样的类...class HandlerChain。为什么我可以在 MyObjectHandler 之后使用通配符,但不能使用此构造?
问题是它V
指示某种特定类型,而不是通配符,因此您需要指定 V 是什么。
换句话说,尽管有一些重复的信息,您的解决方案 3 是正确的方法。不幸的是,您会在 Java 中看到更多这样的情况。当字段上的特定修饰符关键字可以实现相同的效果时(就像在 Ruby 中一样),getter/setter 可以说是不必要的样板。
但请注意,如果您指定public abstract class HandlerChain<T extends MyObjectHandler<V>, V extends MyObject>
,则将链指定为仅适合一种特定类型的MyObjectHandler
。因为我认为您可能需要一系列不同的处理程序,这些处理程序都能够处理相同的对象类型,所以您最好只指定该对象类型:
public abstract class HandlerChain<V extends MyObject> {
private List<MyObjectHandler<V>> handlers;
public HandlerChain(List<MyObjectHandler<V>> handlers) {
this.handlers = handlers;
}
public List<V> doChain(List<V> objects) {
for (MyObjectHandler<V> handler : handlers) {
objects = handler.handle(objects);
}
return objects;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1302 次 |
最近记录: |