Reputation: 9548
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
Reputation: 159086
Change BaseAdapter<IEvent>
to BaseAdapter<? extends IEvent>
on BaseView.events
, and the two getAdapter()
methods.
Upvotes: 1
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