为什么我的自绑定泛型类型与方法调用不匹配? [英] Why does my self-bound generic type not match the method invocation?

查看:56
本文介绍了为什么我的自绑定泛型类型与方法调用不匹配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为如下所示的命令外壳编写代码:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆