繁体   English   中英

使用方法参数超类的接口实现

[英]Interface implementation with method argument superclasses

作为本主题中一般问题的一个实际例子,我想在Set接口中实现containsAll方法

public boolean containsAll(Iterable<?> c) { /* ... */ }

我认为这应该是允许的,因为CollectionIterable意味着这样的containsAll将覆盖接口要求。 同样,更普遍的是能够实现与参数超类的接口似乎应该工作。

然而,Eclipse说没办法(没有试过直接javac) - 有人可以解释原因吗? 我确信规范中的某些内容使其成为现实,但我也想了解需求的动机。 或者我错过了像Iterable<?>这样的东西不是Collection<?>的超类?

作为一个附带问题 - 鉴于我正在声明两种方法,带有Iterable签名的方法在使用Collection参数的调用时总是首选吗?

Eclipse错误:

如果我使用Collection签名删除该方法,只需离开Iterable (请参阅错误后),我会得到以下内容:

The type BitPowerSet must implement the inherited abstract method Set<Long>.containsAll(Collection<?>)

确切的实施是:

@Override public boolean containsAll(Collection<?> c) {
  for (Object o : c) if (!contains(o)) return false;
  return true;
}
public boolean containsAll(Iterable<?> c) {
  for (Object o : c) if (!contains(o)) return false;
  return true;
}

由于您正在实现的接口声明(abstract)方法containsAll(Collection<?>) ,因此必须使用此精确签名实现它。 Java不允许您使用比原始参数类型更宽的参数类型来实现/覆盖方法。 这就是当您使用Collection签名注释掉方法时出现错误的原因。

当没有注释掉该方法时,您没有显示您声称获得的其他错误,但我想它可能需要对模糊方法重载执行某些操作。

我猜测为什么java有这个限制,比如你有:

class A {
    void foo(String s) { ...  }
}

class B extends A {
    // Note generalized type
    @Override void foo(Object s) { ...  }
}

现在,如果你有class C extends B并且它想要覆盖foo ,那么它不清楚应该采用什么参数。

例如,首先直接说C扩展A,重写void foo(String s) ,然后将其更改为扩展B.在这种情况下,C的现有foo覆盖将变为无效,因为B的foo应该能够处理所有Object ,不仅仅是String

参数类型是方法签名的一部分,因此jvm需要一个具有完全相同签名的方法来查找覆盖。 containsAll(Iterable)将具有与containsAll(Collection)不同的签名。

如果我没记错的话,编译器必须使用一些变通方法来使泛型工作尽管有这种限制。

对于第二个问题,编译器更喜欢Collection参数,因为它是Iterable的子类型,这使得Collection方法比Iterable更具体。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM