Reputation: 2736
I am aware of type erasure but this doesn't make sense to me.
class Base{
public <T> Collection<T> transform(Collection<T> list)
{
return new ArrayList<T>();
}
}
And
public class Derived extends Base {
@Override // compilation error
public Collection<CharSequence> transform(Collection<CharSequence> list) {
return new HashSet<CharSequence>();
}
}
An error is generated in my IDE:
'transform(Collection)' in 'Derived' clashes with 'transform(Collection)' in 'Base'; both methods have the same erasure, yet neither overrides the other
My thoughts were we could override transform
without an error from the compiler.
Why transform
in Derived
does not correctly override the method transform
in Base? I know It has to do with type erasure but. I can't understand why.
Upvotes: 2
Views: 702
Reputation: 16276
Base
and Derived
are not generic classes and Collection<T>
in Base
has nothing to do with Collection<CharSequence>
in Derived
- there is no connection between them - hence an error!
You can fix it as follows:
class Base<T> {
public Collection<T> transform(Collection<T> list) {
return new ArrayList<>();
}
}
class Derived extends Base<CharSequence> {
@Override
public Collection<CharSequence> transform(Collection<CharSequence> list) {
return new HashSet<>();
}
}
Otherwise, the valid override would be:
class Derived extends Base {
@Override
public <T> Collection<T> transform(Collection<T> list) {
return new HashSet<>();
}
}
Upvotes: 5
Reputation: 140534
The signature of the method in the base class:
<T> Collection<T> transform(Collection<T> list)
says "I will accept a collection with elements of any type, and return you a collection of elements of that same type.
By the Liskov Substitution Principle, any subclass which implements this method must do the same. In particular, it must accept a collection with elements of any type.
If you try to override this with a method:
Collection<CharSequence> transform(Collection<CharSequence> list)
then it doesn't do what is required: it doesn't accept collection elements of any type, it only accepts elements of a specific type. Hence it doesn't override the superclass method
Normally, there is no problem with defining a method in a subclass which doesn't override a method in the superclass: you can define new methods in the subclass that don't exist in the superclass. But because of type erasure, you can't continue to have both methods, since they have the same signature. Hence, the compiler disallows you from doing this.
Upvotes: 5