2011-08-18 18 views
6

Ho incontrato un problema durante il tentativo di creare un ArrayAdapter generico. Probabilmente è legato alla mia comprensione limitata dei farmaci generici in Java e speravo che qualcuno potesse mettermi in chiaro. Fondamentalmente ho una classe astratta adattatore di base:Generics with ArrayAdapters

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

Poi ho un adattatore che estende questa classe di base:

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

I modelli sono definiti come:

public class BaseModel{...} 

public class SubclassModel extends BaseModel{....} 

Questo non lo fa compilare, come anche se SubclassModel estende BaseModel, le liste di loro non sono equivalenti. Questo thread (Most efficient way to cast List<SubClass> to List<BaseClass>) spiega tanto, e dice di usare questo, invece:

List<? extends BaseModel> 

Quando cambio a:

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

gli errori sul metodo di costruzione vanno via, ma ora c'è una classe errore di livello indicante: getItem (int) in scontri BaseAdapter con getItem (int) in android.widget.ArrayAdapter; tentare di utilizzare il tipo di reso incompatibile.

Sembra che getItem debba restituire un tipo? estende BaseModel, che è - qualcuno può consigliare?

Grazie!

risposta

7

Hmm, la mia Java SDK non ha nemmeno fatemi compilo

public class MyAdapter extends BaseAdapter<? extends BaseModel> 

Si attende una classe illimitata o interfaccia dopo la extends. Ma questo non importa, una soluzione al vostro problema sta cambiando la classe BaseAdapter se questa è un'opzione:

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); 
    } 
} 

Poi

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

con il codice precedente funzionerà.

Edit:

dimenticato di spiegare il motivo per cui la vostra prima soluzione non ha funzionato:

Il Language Spec dice

Sottotipizzazione non si estende attraverso i tipi generici: T <: U non implica che C <: C.

Ciò significa che SubclassModel si estende s BaseModel, questo non implica che Lista estenda Lista.

+0

+1 ..Looks come stavo scrivendo la mia risposta mentre stavate scrivendo la vostra :-) – Kal

+0

pensieri simili , errore simile, soluzione simile, è spaventoso :) – emboss

+0

Abbastanza sicuro - grazie rilievo e Kal! Controllerò la prima risposta. – user888867

0

non riesco a compilare

public class MyAdapter extends BaseAdapter<? extends BaseModel> 

mi dà un errore che dice "Un supertipo non può specificare un carattere jolly".

quello che funziona per me è questo -

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

e questo

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