我正在为如下所示的命令外壳编写代码:
interface Context<C extends Context<C>> {}
interface RecursiveContext<C extends RecursiveContext<C>> extends Context<C> {
Shell<C> getShell();
default Result execute(Command cmd) { return getShell().execute(cmd, this); }
}
interface Shell<C extends Context<C>> {
C newContext();
Result execute(Command cmd, C context);
}
Run Code Online (Sandbox Code Playgroud)
我在默认方法中遇到错误说
The method execute(Command, C) in the type Shell<C> is not applicable for the arguments (Command, RecursiveContext<C>)
Run Code Online (Sandbox Code Playgroud)
我希望这能奏效,因为Shell<C> getShell()保证能够C在其execute调用中接受并且因为this实际上保证是相同自绑定类型的子类型C,但编译器似乎不同意我的观点。哪里不匹配,在默认方法中执行强制转换是否安全?如果这不安全,你能提供一个类型不匹配的反例吗?
我也试过在 shell 中引入一个中间类型<D extends C> execute(Command, D),但这似乎没有改变任何东西。
(大多数建议的问题都涉及原始类型的中间步骤,但我认为我没有错过。)
这里问题的核心是CinRecursiveContext并不是真的Self- 实现类的类型。Java 中没有这样的东西,这RecursiveContext<C extends RecursiveContext<C>>只是解决这个问题的一个技巧,而这正是该技巧中断的地方。
假设我有A和B。这是有效的:
class A implements RecursiveContext<B> {
@Override
public Shell<B> getShell() {
return new ShellB();
}
}
class B implements RecursiveContext<B> {
@Override
public Shell<B> getShell() {
return null;
}
}
class ShellB implements Shell<B>{
@Override
public B newContext() {
return new B();
}
@Override
public Result execute(Command cmd, B context) {
return new Result();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以这样做:
new A().execute(new Command());
Run Code Online (Sandbox Code Playgroud)
现在execute将通过this,这是 的一个实例A,进入ShellB.execute!
真的有人会这样实施RecursiveContext吗?我想不会!人们理解这种RecursiveContext<C extends RecursiveContext<C>>模式并“接受提示”。编译器没有(因为自定界泛型类型在技术上不是语言功能),并且说C仍然可能与this.