Hamza Belmellouki
Hamza Belmellouki

Reputation: 2736

Compilation error when overriding a generic method with a type parameter

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

Answers (2)

Oleksandr Pyrohov
Oleksandr Pyrohov

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

Andy Turner
Andy Turner

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

Related Questions