为什么我的自绑定泛型类型与方法调用不匹配? [英] Why does my self-bound generic type not match the method invocation?
问题描述
我正在为如下所示的命令外壳编写代码:
I'm writing code for a command shell that looks like this:
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);
}
我在使用默认方法时出错
I'm getting an error in the default method saying
The method execute(Command, C) in the type Shell<C> is not applicable for the arguments (Command, RecursiveContext<C>)
由于 Shell< C>保证getShell()
能够在其 execute
调用中接受 C
,并且因为实际上保证了 this
是一个相同的自绑定类型 C
的子类型,但是编译器似乎与我不同意.不匹配在哪里,以默认方法执行强制转换是否安全?如果这样做不安全,能否提供类型不匹配的反例?
I expect this to work, since the Shell<C> getShell()
is guaranteed to be able to accept C
in its execute
call and because this
is in fact guaranteed to be a subtype of the same self-bound type C
, but the compiler does not seem to agree with me. Where's the mismatch, and is it safe to perform a cast in the default method? If this is not safe, can you provide a counterexample of type mismatch?
我还尝试在shell中引入一个中间类型< D扩展C>execute(Command,D)
,但这似乎并没有改变任何东西.
I've also tried introducing an intermediate type in the shell <D extends C> execute(Command, D)
, but that doesn't seem to change anything.
(建议的大多数问题都涉及原始类型的中间步骤,但我认为我没有错过.)
(Most of the suggested questions involve a raw-type intermediate step, but I don't think that I've missed that.)
推荐答案
问题的核心是 RecursiveContext
中的 C
不是真正的 Self
-实现类的类型.在Java中没有这样的东西,并且 RecursiveContext< C扩展了RecursiveContext< C>>
只是解决该问题的一个技巧,而这正是该技巧的地方.
The core of the problem here is that C
in RecursiveContext
is not really Self
- the type of the implementing class. There is no such thing in Java, and this RecursiveContext<C extends RecursiveContext<C>>
is merely a trick to workaround that, and this is where that trick breaks.
假设我有 A
和 B
.这是有效的:
Let's say I have A
and B
. This is valid:
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();
}
}
我可以这样做:
new A().execute(new Command());
现在 execute
会将 this
(是 A
的一个实例)传递到 ShellB.execute
!
Now execute
would pass this
, which is an instance of A
, into ShellB.execute
!
有人会像这样真正实现 RecursiveContext
吗?我认为不会!人们了解此 RecursiveContext< C扩展了RecursiveContext< C>
模式并采用提示".编译器不会这样做(因为自绑定通用类型从技术上讲不是语言功能),并说 C
可能与 this
的类型不同.
Would anyone actually implement RecursiveContext
like that? I would think not! People understand this RecursiveContext<C extends RecursiveContext<C>>
pattern and "takes the hint". The compiler doesn't (because self-bounded generic types is not technically a language feature), and says C
still might not be the same type as this
.
这篇关于为什么我的自绑定泛型类型与方法调用不匹配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!