2013-06-14 21 views
8

Próbuję utworzyć ogólny program ładujący tabelę, którego schemat jest znany w czasie wykonywania. Wymaga to posiadania klasy, która zawiera listę różnych typów elementów i obsługuje różne metody pobierania i ustawiania, takie jak getInt(int index), asString(int index), asStringList(int index). Typy elementów, które rozważam, są następujące: Integer, , String i i i i. Rzeczywisty typ każdego elementu jest znany w czasie wykonywania i zapisuję go na liście opisującej jego schemat do dalszego przetwarzania.Przechowywanie różnych typów elementów na liście w języku Java

Moje pytanie brzmi: czy powinienem przechowywać taką listę elementów w List<Object> lub List<? extends Object>? lub czy istnieje lepszy sposób na wdrożenie takiej klasy?

+0

W czasie wykonywania 'List ' 'List' staje się, więc nie ma szans tu, Musi mieć dwa oddzielne zestawy klas. – fge

+1

To naprawdę nieprzyjemny zapach z kodem, który tam dostałeś. –

+0

@ Brain Roach: Podałem powód, dla którego tego potrzebuję. – keelar

Odpowiedz

11

Ponieważ wspólny przodek klasach jest Object, a ponieważ List<? extends Object> nie domiar jakichkolwiek środków czyszczących (po wszystkim, wszystko przebiega Object) wygląda List<Object> byłoby OK wybór.

Jednak taka lista byłaby mieszana: należy sprawdzić typ obiektu podczas pracy i podejmować w tym celu decyzje. To zdecydowanie nie jest dobra rzecz.

Lepszą alternatywą byłoby stworzenie własnej klasy, która implementuje operacje na elementach listy w sposób jednolity i utworzenie jednej podklasy dla każdego podtypu, który implementuje te operacje w różny sposób. Umożliwiłoby to potraktowanie listy w jednolity sposób, przesuwając różnicowanie poszczególnych obiektów do opakowań.

public interface ItemWrapper { 
    int calculateSomething(); 
} 

public abstract class IntWrapper implements ItemWrapper { 
    private int value; 

    public IntWrapper(int v) { 
     value=v; 
    } 

    public int calculateSomething() { 
     return value; 
    } 
} 

public abstract class DoubleListWrapper implements ItemWrapper { 
    private List<Double> list; 

    public DoubleListWrapper (List<Double> lst) { 
     list = lst; 
    } 

    public int calculateSomething() { 
     int res; 
     for (Double d : list) { 
      res += d; 
     } 

     return res; 
    } 
} 
// ...and so on 

Teraz można zrobić listę ItemWrapper obiektów i calculateSomething na nich bez sprawdzania ich typ:

List<ItemWrapper> myList = new ArrayList<ItemWrapper>(); 

for (ItemWrapper w : myList) { 
    System.out.println(
     w.calculateSomething()); 
} 
+0

Dlaczego dostaję "Abstrakcyjne metody nie mogą mieć ciała" na "publicznej abstrakcyjnej int"? – Zon

+0

@Zon Ponieważ był to mój błąd kopiowania/wklejania :-) Dziękuję za wskazanie. – dasblinkenlight

+0

myList jest zawsze pusty i drukowanie jest niedostępne. Jak możemy dodać ItemWrapper do myList przed zapętleniem, jeśli nie ma tam klasy ItemWrapper (tylko interfejs)? – Zon

4

Powinieneś użyć List<Object>, lub jakiejkolwiek super klasy jest najbliższy pasuje. Kiedyś zadałem podobne pytanie, które zebrało kilka bardzo dobrych odpowiedzi, które mają dla ciebie wiele istotnych informacji. I would check it out. Zasadniczo wszystko sprowadza się do PECS - Producer Extends, Consumer Super.

+0

Dziękuję za wskazówkę, próbowałem, ale nie znalazłem tego wpisu. Dziękujemy za przekazanie tych informacji. – keelar

+0

bez problemu. miał podobny problem raz :) – oligofren

Powiązane problemy