开发者

Generics with ArrayAdapters

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 Su开发者_如何学运维bclassModel 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.


I can't compile

public class MyAdapter extends BaseAdapter<? extends BaseModel> 

Gives me an error saying "A supertype may not specify a wildcard".

What does work for me is this --

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

and this

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜