简体   繁体   English

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

[英]Interface implementation with method argument superclasses

As a practical example of the general question in the subject, I'd like to implement the containsAll method in the Set interface with 作为本主题中一般问题的一个实际例子,我想在Set接口中实现containsAll方法

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

I figure this should be allowed, since Collection is Iterable meaning such a containsAll would cover the interface requirement. 我认为这应该是允许的,因为CollectionIterable意味着这样的containsAll将覆盖接口要求。 Likewise, more generally being able to implement interfaces with argument superclasses seems like it should work. 同样,更普遍的是能够实现与参数超类的接口似乎应该工作。

However, Eclipse says no way (haven't tried just javac straight-up) - can someone explain the reason for that? 然而,Eclipse说没办法(没有试过直接javac) - 有人可以解释原因吗? I'm sure there's something in the spec which makes it the way it is, but I'd like to understand the motivation for requirement as well. 我确信规范中的某些内容使其成为现实,但我也想了解需求的动机。 Or am I missing something like Iterable<?> not being a superclass of Collection<?> ? 或者我错过了像Iterable<?>这样的东西不是Collection<?>的超类?

As a side question - given I'm declaring two methods would the method with the Iterable signature always be preferred on calls with a Collection argument? 作为一个附带问题 - 鉴于我正在声明两种方法,带有Iterable签名的方法在使用Collection参数的调用时总是首选吗?

Eclipse Error: Eclipse错误:

If I remove the method with the Collection signature, just leaving the Iterable one (see after error), I get the following: 如果我使用Collection签名删除该方法,只需离开Iterable (请参阅错误后),我会得到以下内容:

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

The exact implementation being: 确切的实施是:

@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;
}

Since the interface you are implementing declares the (abstract) method containsAll(Collection<?>) , you must implement it with this exact signature. 由于您正在实现的接口声明(abstract)方法containsAll(Collection<?>) ,因此必须使用此精确签名实现它。 Java does not allow you to implement/override a method with a wider parameter type than the original. Java不允许您使用比原始参数类型更宽的参数类型来实现/覆盖方法。 This is why you get the error you show when you comment out your method with the Collection signature. 这就是当您使用Collection签名注释掉方法时出现错误的原因。

You don't show the other error you claim to get when the method is not commented out, but I guess it might have to do something with ambiguous method overloading. 当没有注释掉该方法时,您没有显示您声称获得的其他错误,但我想它可能需要对模糊方法重载执行某些操作。

My guess as to why java has this restriction is, say you have: 我猜测为什么java有这个限制,比如你有:

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

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

Now if you have class C extends B and it wants to override foo , it's not clear what argument it should take. 现在,如果你有class C extends B并且它想要覆盖foo ,那么它不清楚应该采用什么参数。

Say for example C extended A directly at first, overriding void foo(String s) , and then it was changed to extend B. In this case C's existing override of foo would become invalid because B's foo should be able to handle all Object s, not just String s. 例如,首先直接说C扩展A,重写void foo(String s) ,然后将其更改为扩展B.在这种情况下,C的现有foo覆盖将变为无效,因为B的foo应该能够处理所有Object ,不仅仅是String

The argument types are part of the method signature so the jvm needs a method with exact the same signature to find overrides. 参数类型是方法签名的一部分,因此jvm需要一个具有完全相同签名的方法来查找覆盖。 A containsAll( Iterable) will have a different signature than containsAll(Collection). containsAll(Iterable)将具有与containsAll(Collection)不同的签名。

If I remember right the compiler has to use some workarounds to make generics work in spite of this limitation. 如果我没记错的话,编译器必须使用一些变通方法来使泛型工作尽管有这种限制。

To your second question, the compiler would prefer the Collection argument since it is a subtype of Iterable, this makes the Collection method more specific than the Iterable one. 对于第二个问题,编译器更喜欢Collection参数,因为它是Iterable的子类型,这使得Collection方法比Iterable更具体。

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

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