2010-02-10 16 views
5

Bugün, sorgulanabilir bulduğum bir kodla karşılaştım. İşte basitleştirilmiş bir örnek (gerçekçi değil).Java jeneriklerini koleksiyonları döndüren arabirimlerde kullanma. En iyi pratik? Tuzaklar?

public interface IListable { 
    //returns first n items from list 
    public ArrayList getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList getLastNThings(int n); 
} 

Sonra şöyle bir implementor var:

public GroceryList implements IListable { 
    private ArrayList<GroceryItem> groceries; 

    public GroceryList() { 
     this.groceries = new ArrayList<GroceryItem>(); 
    } 

    public ArrayList<GroceryItem> getFirstNThings(int n) { 
     ArrayList<GroceryItem> firstNThings = new ArrayList<GroceryItem>(); 
     for (int i=0; i < n; i++) { 
      firstNThings.add(this.groceries.get(i)); 
     } 
     return firstNThings 
    } 

    public ArrayList<GroceryItem> getLastNThings(int n) { 
     ArrayList<GroceryItem> lastNThings = new ArrayList<GroceryItem>(); 
     for (int i=this.groceries.size(); i < this.groceries.size()-n; i--) { 
      lastNThings.add(this.groceries.get(i-1); 
     } 
     return lastNThings; 
     } 
} 

Eğer (Ben de birkaç bulundu) ki bulabilirsiniz uygulama sorunlarını görmezden. Ne alıyorum, arabirimin ArrayList (yani ArrayList <?>) Için herhangi bir genel tür parametresi kullanmadığı, ancak arabirimin yönteminin uygulayıcısının (yani ArrayList < GroceryList>) yaptığıdır. Diğer uygulamacılar ArrayList'leri başka tip parametrelere de dönüştürebilirler, değil mi?

Sorularım: Bu bir problem mi? Bir şeyleri tekrar gözden geçirmeli miyim? Buna değer mi? Avantajı nedir? Dönüş tipi ham tip olan bir arabirimde tanımlanmış bir yönteme sahip olsaydım ne tür sorunlar yaşayabilirim, ancak yöntemin gerçek uygulayıcıları çeşitli parametreli türler döndürüyor mu? IListable her iki yöntemler hep aynı tür dönerseniz

+2

Sfussenegger'in ne dediğinin yanı sıra, "ArrayList" yerine "List" i döndürme yöntemlerini tercih ederim. –

cevap

5

yerine bunu kullanın:

public interface IListable<T> { 
    //returns first n items from list 
    public ArrayList<T> getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList<T> getLastNThings(int n); 
} 

bu bir seçenek değilse, kullanmayı deneyin? yerine. Temelde aynı olsa da, çirkin uyarıları önler.

public interface IListable { 
    //returns first n items from list 
    public ArrayList<?> getFirstNThings(int n); 

    //returns last n items from list 
    public ArrayList<?> getLastNThings(int n); 
} 

Genel olarak, bir süper-tipi veya arayüzünde daha bir uygulamada daha belirgin bir dönüş türü kullanmak için bir sorun değil. IListable ile uğraşıyorsanız, iade edilen listedeki herhangi bir nesne tipini kullanmanız gerekir. Eğer GroceryList ile uğraşıyorsanız, sadece Bakkal Ürünleri beklersiniz. Bu yalnızca türlerin genetik türü argümanları için değil, dönüş türünün kendisi için de geçerlidir. Yani bir arabirim List<Foo> get() belirtiyorsa, ArrayList<Foo> get() olarak uygulamak için tamamdır. Eğer null dönmemesi gibi

+0

Bu yöntem aynı zamanda, MarketList'i daha sonra yeniden kullanmak için tamamen genel yazılan bir liste haline getirmenizi sağlar. – Thirler

0

En iyi uygulama, sizin Açık kodunda bir List<?>ile saf joker asla geri etmektir.

Java'daki joker karakter jenerik kodları, kodunuzu kullanarak tüm kodlayıcılara bulaşacaktır. Yerel sorunu çözmek için Close kodunuzda yapabilirsiniz.

Genellikle, List<? extends User> ve List<? super User>

Eğer ne yaptığınızı bilir ve PECS ve bounded wildcards ilgili her şeyi okursanız Yapabilirsin gibi kovaryans ve contravariance joker dönmek önleyecektir. Sadece bunu yapamadığı için yapmayın.

İlgili konular