2011-08-18 30 views
6

Tôi đã gặp sự cố khi cố gắng tạo một ArrayAdapter chung. Nó có lẽ liên quan đến sự hiểu biết giới hạn của tôi về Generics trong Java và hy vọng ai đó có thể đặt tôi thẳng. Về cơ bản tôi có một abstract class bộ chuyển đổi cơ sở: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); 
    } 
    .... 
} 

Sau đó, tôi đã một adapter mở rộng lớp cơ sở này:

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

Các mô hình được định nghĩa là:

public class BaseModel{...} 

public class SubclassModel extends BaseModel{....} 

Điều này không biên dịch, mặc dù SubclassModel mở rộng BaseModel, Danh sách của chúng không tương đương. chủ đề này (Most efficient way to cast List<SubClass> to List<BaseClass>) giải thích càng nhiều, và nói để sử dụng này để thay thế:

List<? extends BaseModel> 

Khi tôi thay đổi để:

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

các lỗi về việc xây dựng phương pháp biến mất, nhưng bây giờ có một lớp lỗi cấp độ nêu rõ: getItem (int) trong các xung đột BaseAdapter với getItem (int) trong android.widget.ArrayAdapter; cố gắng sử dụng loại trả về không tương thích.

Dường như getItem phải trả về loại? mở rộng BaseModel, nó là ai - ai cũng có thể tư vấn?

Cảm ơn!

Trả lời

7

Hmm, Java SDK của tôi thậm chí còn không cho tôi biên dịch

public class MyAdapter extends BaseAdapter<? extends BaseModel> 

Nó hy vọng một lớp không giới hạn hoặc giao diện sau khi extends. Nhưng điều đó không quan trọng, một giải pháp cho vấn đề của bạn đang thay đổi lớp BaseAdapter nếu đó là một lựa chọn:

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

Sau đó

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

với mã trước đó sẽ làm việc.

Edit:

Quên để giải thích tại sao giải pháp đầu tiên của bạn không làm việc:

Các Language Spec nói

subtyping không mở rộng thông qua các loại chung: T <: U không bao hàm rằng C <: C.

Điều này có nghĩa là mặc dù SubclassModel mở rộng s BaseModel, điều này không ngụ ý rằng Danh sách mở rộng Danh sách.

+0

+1 ..Looks như tôi đã gõ câu trả lời của tôi trong khi bạn đang đăng của bạn :-) – Kal

+0

những suy nghĩ tương tự , lỗi tương tự, giải pháp tương tự, đó là đáng sợ :) – emboss

+0

Chắc chắn đủ - cảm ơn emboss và Kal! Tôi sẽ kiểm tra câu trả lời đầu tiên. – user888867

0

tôi không thể biên dịch

public class MyAdapter extends BaseAdapter<? extends BaseModel> 

Cung cấp cho tôi một lỗi nói rằng "Một siêu kiểu có thể không chỉ định một ký tự đại diện".

gì làm việc đối với tôi là này -

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

và điều này

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