I've run into a problem while trying to create a generic ArrayAdapter. It probably is related to my limited understanding of generics in Java and was hoping somebody could set me straight. Basically I have an abstract base adapter class:
public abstract class BaseAdapter<T> extends ArrayAdapter<T>
{
....
private List<T> items;
....
protected abstract List<T> build(JSONArray jsonArray);
....
@Override
public T getItem(int position)
{
return items.get(position);
}
....
}
Then I have an adapter that extends this base class:
public class MyAdapter extends BaseAdapter<BaseModel>
{
....
@Override
protected List<BaseModel> build(JSONArray jsonArray)
{
if (useBaseModel())
{
return BaseModel.buildBaseModels(jsonArray); //returns List<BaseModel>
}
else
{
return SubclassModel.buildSubclassModels(jsonArray); //returns List<SubclassModel>
}
}
....
}
The models are defined as:
public class BaseModel{...}
public class SubclassModel extends BaseModel{....}
This does not compile, as even though SubclassModel extends BaseModel, Lists of them are not equivalent. This thread ( Most efficient way to cast List<SubClass> to List<BaseClass> ) explains as much, and says to use this instead:
List<? extends BaseModel>
When I change to:
public class MyAdapter extends BaseAdapter<? extends BaseModel>
{
...
protected List<? extends BaseModel> build(JSONArray jsonArray)
...
}
the errors on the build method go away, but now there is a class level error stating: getItem(int) in BaseAdapter clashes with getItem(int) in android.widget.ArrayAdapter; attempting to use incompatible return type.
It seems as though getItem should be returning a type ? extends BaseModel, which it is -- can anybody advise?
Thanks!
Hmm, my Java SDK doesn't even let me compile
public class MyAdapter extends BaseAdapter<? extends BaseModel>
It expects an unbounded class or interface after the extends
. But that doesn't matter, a solution to your problem is changing the BaseAdapter
class if that is an option:
public abstract class BaseAdapter<T> extends ArrayAdapter<T>
{
....
private List<T> items;
....
protected abstract List<? extends T> build(JSONArray jsonArray);
....
@Override
public T getItem(int position)
{
return items.get(position);
}
}
Then
public class MyAdapter extends BaseAdapter<BaseModel>
{
...
protected List<? extends BaseModel> build(JSONArray jsonArray)
...
}
with the previous code will work.
Edit:
Forgot to explain why your first solution didn't work:
The Language Spec says
Subtyping does not extend through generic types: T <: U does not imply that C <: C.
This means although SubclassModel extends BaseModel, this does not imply that List extends List.
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