As a practical example of the general question in the subject, I'd like to implement the containsAll
method in the Set
interface with
public boolean containsAll(Iterable<?> c) { /* ... */ }
I figure this should be allowed, since Collection
is Iterable
meaning such a containsAll
would cover the interface requirement. 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? 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<?>
?
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?
Eclipse Error:
If I remove the method with the Collection
signature, just leaving the Iterable
one (see after error), I get the following:
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;
}
My guess as to why java has this restriction is, say you have:
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.
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.