Zbarcea Christian
Zbarcea Christian

Reputation: 9548

Java: Override generic method

I'm trying to override a method in a child class which inherits an abstract method from the parent. I'm trying to change the generic return type, but I'm a bit confused.

The base generic class:

public abstract class BaseAdapter<T extends IEvent> {
   private List<T> events;

   public BaseAdapter(List<T> events) {
      this.events = events;
   }

   public List<T> sort() {
      // Some sorting...
      return newFilteredEvents;
   }
}

The child class:

public class AdapterEvent extends BaseAdapter<Event> {
   public AdapterEvents(List<Event> events) {
      super(events);
   }
}

The implementation:

public abstract class BaseView extends View {

   private BaseAdapter<IEvent> events;

   @Override
   protected View onCreate(Context context) {
       View view = super.onCreate(context);

       this.events = getAdapter();

       return view;
   }

   /**
    * The child class should provide an adapter
    */
   protected abstract BaseAdapter<IEvent> getAdapter();
}

The child View class where I would like to override the parameterized method:

public class EventView extends BaseView {

   @Override
   protected View onCreate(Context context) {
      return super.onCreate(context):
   }

   @Override
   protected BaseAdapter<IEvent> getAdapter() {
      List<Event> events = EventManager.getInstance().getEvents();

      return new AdapterEvent(events);
   }

}

This is where Eclipse is throwing an error message:

Type mismatch: cannot convert from AdapterEvents to BaseAdapter<IEvent>

Note the class and the interface: Event and IEvent:

public interface IEvent {
   public void setId(long id);
   public long getId();

   public void setStartMillis(long start);
   public long getStartMillis();

   public void setEndMillis(long end);
   public long getEndMillis();
}

And the Model class which inherits from IEvent

public class Event implements IEvent {
   private long id;
   private long startTime, endTime;

   @Override
   public void setId(long id) {
      this.id = id;
   }

   @Override
   public long getId() {
      return this.id;
   }

   // The other inherited methods...
}

What I'm trying to achieve is to write much more abstract code, because these classes, interfaces will be extended by multiple classes (diferent View types in my case). These are the abstract classes: BaseAdapter, BaseView, IEvent, and these are the implementations: AdapterEvent, EventView, Event.

Upvotes: 2

Views: 244

Answers (2)

Andreas
Andreas

Reputation: 159086

Change BaseAdapter<IEvent> to BaseAdapter<? extends IEvent> on BaseView.events, and the two getAdapter() methods.

Upvotes: 1

Jack
Jack

Reputation: 133557

This because there is no covariance in type variables of generics in Java.

This means that you don't have polymorphism for a generic type if the type argument is polymorphic to the required one. In practice List<Event> is not a subtype of List<IEvent> even though Event is-a IEvent.

That's why Java provides wildcards:

protected abstract BaseAdapter<? extends IEvent> getAdapter();

So that you can do:

protected BaseAdapter<? extends IEvent> getAdapter() {
  ..
  return new AdapterEvent(events);
}

Basically you are telling the compiler that getAdapter returns a BaseAdapter of an unspecified type which extends IEvent. This allows what you need.

Upvotes: 4

Related Questions