Common with ArrayAdapters

I had a problem while trying to create a generic ArrayAdapter. This is probably due to my limited understanding of Java generics and was hoping that someone could install me. I basically have an abstract base adapter:

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> } } .... } 

Models are defined as:

 public class BaseModel{...} public class SubclassModel extends BaseModel{....} 

This does not compile, since SubclassModel extends BaseModel, lists of them are not equivalent. This thread ( The most efficient way to cast a List <SubClass> to a <BaseClass> list ) explains the same and says to use it instead:

 List<? extends BaseModel> 

When I go to:

 public class MyAdapter extends BaseAdapter<? extends BaseModel> { ... protected List<? extends BaseModel> build(JSONArray jsonArray) ... } 

assembly method errors go away, but now a class-level error occurs: getItem (int) in conflicts between BaseAdapter and getItem (int) in android.widget.ArrayAdapter; trying to use an incompatible return type.

It seems that getItem should return a type? extends BaseModel as it is - can anyone advise?

Thanks!

+6
source share
2 answers

Hmm, my Java SDK doesn't even let me compile

 public class MyAdapter extends BaseAdapter<? extends BaseModel> 

It expects an unlimited class or interface after extends . But it does not matter, the solution to your problem changes the BaseAdapter class, if this 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:

I forgot to explain why your first solution did not help:

Language Spec says

Subtyping does not apply to common types: T <: U does not mean that C <: C.

This means that although SubclassModel extends BaseModel, it does not mean List extends List.

+7
source

I can not compile

 public class MyAdapter extends BaseAdapter<? extends BaseModel> 

Gives me an error: "Supertype cannot specify a wildcard."

It works for me -

 public abstract class BaseAdapter<T> extends ArrayAdapter<T> { private List<? extends T> items; protected abstract List<? extends T> build(JSONArray jsonArray); } 

and this one

 public class MyAdapter extends BaseAdapter<BaseModel> { protected List<? extends BaseModel> build(JSONArray jsonArray); } 
0
source

Source: https://habr.com/ru/post/895365/


All Articles