I had a hard time thinking of a title for this, so do forgive me.
I have an interface with the following methods:
public interface Algorithm<E,F> {
public Set<? extends Algorithm<E,F>> map(int numPartitions);
public F reduce(Set<? extends Algorithm<E,F>> partitions);
}
and a class implementing Algorithm
with the following methods:
public class LinearSearch<T> implements Algorithm<List<T>, Integer> {
@Override
public Set<LinearSearch<T>> map(int numPartitions) {
return null;
}
@Override
public Integer reduce(Set<LinearSearch<T>> partitions) {
return null;
}
}
Now the odd thing is that Eclipse is complaining about the second method, reduce
.
The method reduce(Set<LinearSearch<T>>) of type LinearSearch<T> must override or implement a supertype method.
This is despite the fact that the map
method is fine. So where am I going wrong?
Overriding Methods and Parameter Types
On the reduce
method, the parameter must be a Set<? extends Algorithm<List<T>,Integer>>
. It must take any Set<? extends Algorithm<List<T>,Integer>>
, not just a Set<LinearSearch<T>>
. You cannot narrow the parameter type while overriding the method.
The JLS, Section 8.4.8.1 elaborates on the signatures of overriding methods:
An instance method m1, declared in class C, overrides another instance method m2, declared in class A iff all of the following are true:
C is a subclass of A.
The signature of m1 is a subsignature (§8.4.2) of the signature of m2.
Either:
m2 is public, protected, or declared with default access in the same package as C, or
m1 overrides a method m3 (m3 distinct from m1, m3 distinct from m2), such that m3 overrides m2.
Here, "subsignature" refers to the parameter types matching, after type erasure.
Overriding Methods and Return Types
But why does the map
method work? Because Java allows the developer to narrow the return type of overriding methods on subclasses.
A different section of the JLS, 8.4.5, covers return types in overriding methods:
Return types may vary among methods that override each other if the return types are reference types. The notion of return-type-substitutability supports covariant returns, that is, the specialization of the return type to a subtype.
A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2, if and only if the following conditions hold:
If R1 is void then R2 is void.
If R1 is a primitive type, then R2 is identical to R1.
If R1 is a reference type then:
R1 is either a subtype of R2 or R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9), or
R1 = |R2|
(emphasis mine)
Your method header should be as follows
public Integer reduce(Set<? extends Algorithm<List<T>, Integer>> partitions)
In order to override a method you must use exactly the same parameter types. If not, it is not considered to be the same method.
Note that types <E,F>
are the parameterized part of that header, so that's where Java gives you some freedom and lets you use the types specified in the class definition.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With