所以我想实现责任链,但使用泛型,上限。
public abstract class Handler<C extends Command> {
private Handler<? extends Command> successor;
public Handler(Handler<? extends Command> successor) {
this.successor = successor;
}
public final String handle(C cmd) {
if (canHandle(cmd)) {
return doHandle(cmd);
} else {
// The method doHandle(capture#3-of ? extends Command) in the type Handler<capture#3-of ? extends Command>
// is not applicable for the arguments (C)
return successor.doHandle(cmd);
}
}
protected abstract boolean canHandle(C cmd);
protected abstract String doHandle(C cmd);
}
abstract class Command {
public String getParamBase() {
return "base";
}
}
class CommandTypeOne extends Command {
public String getTypeOneParam() {
return "ParamTypeOne";
}
}
class CommandTypeTwo extends Command {
public String getTypeTwoParam() {
return "ParamTypeTwo";
}
}
当然,我可以让这个类非泛型,并且在任何地方都有Command作为参数,这样就行了。但是我不想在doHandle方法中使用强制转换来传递给Command的相应子类型。我希望为每个子类型设置一个处理程序,通用,并将它们链接起来。
我得到的问题是: Handler类型中的方法doHandle(捕获#3-of?extends Command)不适用于参数(C)
为什么C扩展Command?
答案 0 :(得分:1)
想象一下,如果您将Command
替换为Animal
(Cat
和Dog
的超类),会发生什么。
successor
引用的签名表示它可以处理某种类型的动物,比如说Cats。另一方面,cmd
方法的handle()
参数也表示要处理的命令可以是Animal的任何其他子类型 - 这里,Dog
可以是有效类型。 / p>
你看,没有什么能保证successor
处理程序能够管理特定类型的命令,所以编译器会有点生气。
答案 1 :(得分:1)
您的字段后继者可以拥有一个实际为Handler<CommandTypeOne>
的实例,因为它可以保存所有内容C extends Command
。其doHandle
方法的签名为String doHandle(CommandTypeOne cmd)
。如果您随后在successor.doHandle()
中拨打handle()
,则会传递一个仅保证为Command
但不是CommandTypeOne
的参数。
也许你应该看看PECS。制片人延伸 - 消费者超级。你可以google它。在您的情况下,您的doHandle方法是消费者,您应该使用super而不是extends。
在这种情况下我可能没有通用。将命令放在C所在的位置。这允许将命令和子类型传递给处理程序链。要允许处理程序区分命令,您可以为可能使用String或int的命令建立id。或者您可以使用instanceof来允许处理程序检查特定的命令子类型。这两种解决方案都不是面向对象的。
此时,您的Command感觉就像一个具有不同内容的数据容器,具体取决于您的子类型。
答案 2 :(得分:0)
这是你的Handler类
//In your case 'C extends Command' in class declaration will be enough
public abstract class Handler<C extends Command> {
private Handler<C> successor;
public Handler(Handler<C> successor) {
this.successor = successor;
}
public final String handle(C cmd) {
if (canHandle(cmd)) {
return doHandle(cmd);
} else {
// The method doHandle(capture#3-of ? extends Command) in the type Handler<capture#3-of ? extends Command>
// is not applicable for the arguments (C)
return successor.doHandle(cmd);
}
}
protected abstract boolean canHandle(C cmd);
protected abstract String doHandle(C cmd);
}