2

所以我想实现责任链,但使用泛型,有上限。

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 子类型。我想为每个子类型、泛型都有一个处理程序,然后将它们链接起来。

我得到的问题是:类型处理程序中的方法 doHandle(capture#3-of ? extends Command) 不适用于参数(C)

为什么如果 C 扩展命令?

4

3 回答 3

1

您的字段后继者可以保存一个真正为 a 的实例,Handler<CommandTypeOne>因为它可以保存所有内容,只要C extends Command. 其doHandle方法的签名是String doHandle(CommandTypeOne cmd). 如果您随后调用successor.doHandle()handle()您将传递一个仅保证为 aCommand而不是 a的参数CommandTypeOne

也许你应该看看PECS。生产者扩展 - 消费者超级。你可以谷歌一下。在您的情况下,您的 doHandle 方法是消费者,您应该使用 super 而不是 extends。

在这种情况下,我可能会不使用泛型。将 Command 放在现在 C 所在的位置。这允许将命令和子类型传递给处理程序链。为了允许处理程序区分命令,您可以为可能带有 String 或 int 的命令建立一个 id。或者您可以使用 instanceof 来允许处理程序检查特定的命令子类型。这两种解决方案都不是非常面向对象的。

此时,您的 Command 感觉就像一个数据容器,根据您的子类型具有不同的内容。

于 2015-04-16T19:29:09.057 回答
1

想象一下如果你替换Command为( and的Animal超类) 会发生什么。CatDog

引用的签名successor说它可以处理某种类型的动物,比如猫。另一方面,cmd该方法的参数handle()还表示要处理的命令可以是 Animal 的任何其他子类型 - 这里Dog可以是有效类型。

您会看到,无法保证successor处理程序能够管理特定类型的命令,因此编译器会有些生气。

于 2015-04-16T19:11:25.893 回答
0

这是你的处理程序类

//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);

}

于 2015-04-16T19:14:42.787 回答