【问题标题】:Surprised that v1 of this program compiles but not v2. Is this by design? If so, why?很惊讶这个程序的 v1 编译但不是 v2。这是设计使然吗?如果是这样,为什么?
【发布时间】:2012-12-23 07:27:48
【问题描述】:

第一版:

public interface DeepCopyable<T>
{
  T deepCopy();
}

public interface Statement extends DeepCopyable<Statement>
{
}

public interface Expression
{
  Expression deepCopy(); // forgot I have an interface for this
}

public class Invocation implements Expression, Statement
{
  public final String Field;

  public Invocation(String field)
  {
    Field = field;
  }

  public Invocation deepCopy()
  {
    return new Invocation(Field);
  }
}

第二版,更新表达式接口:

public interface Expression extends DeepCopyable<Expression>
{
}

但是现在我得到了编译错误

Error: C:\temp\Invocation.java:1: DeepCopyable cannot be inherited with different arguments: <Expression> and <Statement>

在返回类型不变的一般情况下,我可以理解此错误消息;但是,如果我两次使用返回类型 A 和 B 继承相同的接口,并且进一步,实现方法返回 C,其中 C 与 A 和 B 是协变的,这不应该是安全的吗?

【问题讨论】:

  • 能否请您发布第二版的完整代码,因为我没有收到任何编译错误。

标签: java generics inheritance covariance


【解决方案1】:

在 Invocation 类中,您正在扩展两个接口 Expression 和 Statement,在您的代码的第二个版本中,您的 Expression 接口正在扩展 DeepcCopyable 接口,如下所示。

class Invocation implements Expression, Statement {...}




interface Statement extends DeepCopyable<Statement> {
}

interface Expression extends DeepCopyable<Expression> {
}

在您的代码中,当您实现两个接口 Expression 和 Statement 时会发生这种情况,这两个接口扩展到不同的泛型,这里发生的情况是编译器对要考虑的内容感到困惑,因此它不允许您同时实现接口 Expression、Statement同一个班级。

【讨论】:

    【解决方案2】:

    您不能使用不同的参数两次实现一个接口。这就是第二个版本的问题。

    第一个版本的问题是它的两个接口都指定了deepCopy,但签名略有不同。但是,它实现的签名是兼容两者的,所以没有问题。

    【讨论】:

      猜你喜欢
      • 2014-09-29
      • 2019-06-22
      • 2011-08-25
      • 2021-12-17
      • 2021-08-26
      • 2016-04-01
      • 2012-04-23
      • 1970-01-01
      • 2022-10-04
      相关资源
      最近更新 更多