2008-12-11 17 views
8

Entschuldigung, ich dachte, dies sei eine Vererbungsfrage: es war die ganze Zeit eine ArrayList-Frage!Casting zwischen ArrayLists in Java

Ok, mein Problem ist spezifischer als ich dachte. Also habe ich zwei Klassenfamilien. Karten und Zonen. Zonen sind Boxen für die Karte.

Die ersten beiden Unterklassen von Zone, ZoneList und ZoneMap sind zwei verschiedene Arten zum Speichern von Karten. Weitere Unterklassen wie Hand und PokerHand haben ihre eigenen spezifischen Möglichkeiten, mit den Karten umzugehen, die sie speichern.

Wo es kompliziert wird ist, dass Card auch Unterklassen hat, wie PokerCard, und dass die Unterklassen von ZoneList und ZoneMap diese organisieren sollen.

Also in ZoneList habe ich protected ArrayList<Card> cardBox; und in PokerHand erwartet, dass ich cardBox = new ArrayList<PokerCard>(); erklären kann, da PokerCard eine Karte ist. Der Fehler, den ich bekomme, ist, dass ich anscheinend nicht zwischen Karte und GangCard sprechen kann, wenn es zu ArrayLists kommt ... Also habe ich versucht, dies zu beheben, indem ich einfach cardBox innerhalb von PokerHand als deklarierte, aber das führte zu dem versteckten Bug up mein Programm.

SO wirklich, ist die Frage über das Gießen zwischen ArrayLists? Java sagt mir, ich kann nicht, also irgendwelche Ideen, wie ich kann?

z.

+0

Kommen Sie, daran zu denken! Eine andere Situation, die ich denke, ist ähnlich, wenn ich getElementAt() aufrufen; und es gibt mir ein GImage zurück, das ich nicht wie ein GImage behandeln kann! Java ruft alle auf, wenn ich versuche, GImage.getName() aufzurufen; oder etwas, weil es kein Bild ist, sondern ein Objekt ...! – Ziggy

Antwort

11

Wenn ich Sie richtig verstehe, dann sollten Sie erklären:

public class ZoneList<T extends Card> { 
    protected List<T> cardBox; 
} 

public class PokerHand extends ZoneList<PokerCard> { 
    public PokerHand() { 
     cardBox = new ArrayList<PokerCard>(); 
    } 
} 
+0

Oh Mann! Das ist auch toll. Ich dachte total "wäre es nicht toll, wenn ich wüsste, wie man Typen als Parameter übergibt ..." und jetzt tue ich es total! Freund! – Ziggy

+1

Wenn Sie ZoneList generisch machen möchten, können Sie CardBox in ZoneList initialisieren: Liste cardBox = new ArrayList (); –

1

Dies hängt davon ab, was die Zugriffskontrolle auf dem Arraylist in Zonelist ist. Meine Annahme von der Debugger-Anweisung ist, dass es entweder nicht markiert, öffentlich oder geschützt ist. Eine Unterklasse kann die Variable einer übergeordneten Klasse, auf die sie zugreifen kann, ausblenden, indem sie eine Variable mit demselben Namen definiert. Sie können auch das Schlüsselwort this verwenden, um auf die bestimmte Objektinstanz zu verweisen, und das Schlüsselwort super, um auf den übergeordneten Schlüssel zu verweisen.

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Diese Sie könnten auch hilfreich für

http://java.sys-con.com/node/46344

+0

Ich glaube nicht, dass es sich um ein Problem bei der Zugriffssteuerung handelt - es handelt sich um ein generisches Varianzproblem. –

10

Zunächst einmal, es ist in der Regel eine bessere Praxis zu nutzen:

Hier ist eine gute Verbindung zu den grundlegenden Zugangskontrolle in Java ist Getter/Setter-Methoden als direkt auf Eigenschaften zugreifen, vor allem, wenn Sie eine komplizierte Vererbung durchführen.

Wie für das Generika-Problem, man kann die CardBox Getter in der übergeordneten Klasse versuchen zu definieren (oder Top-Level-Interface/abstrakte Klasse) als:

protected ArrayList<? extends Card> getCardBox(); 

Auf diese Weise können Sie es in Subklassen ovverride und sie Gibt eine Liste aller Unterklassen von Card zurück.

+0

Ah! Ich wusste nicht, dass ich das tun könnte: das ist großartig! Vielen Dank! – Ziggy

+0

Bei Verwendung dieses dingy, wie soll ich die ArrayLists initialisieren? einfach nur altes Feld = neue ArrayList (); gibt mir einen Fehler zurück? ... – Ziggy

+1

In der Unterklasse würden Sie eine Liste als eine Eigenschaft mit 'private final List instanziieren cardBox = new ArrayList ()' Diese Liste würde von der Methode getCardBox zurückgegeben werden. – boutta

19

Marc und kolstae haben gute Antworten in Bezug auf gegeben, wie um das Problem zu bekommen, aber ich denke, es lohnt sich zu erklären warum Original Code funktioniert nicht.

Um die Sache zu vereinfachen, tendiere ich dazu, das Problem in Bezug auf Obst zu stellen.Angenommen, wir haben:

List<Banana> bananaBunch = new ArrayList<Banana>(); 
List<Fruit> fruitBowl = bananBunch; 
fruitBowl.add(new Apple()); 

Wenn dies erlaubt ist, wir mit einem Apfel in einem Bündel Bananen am Ende, das ist natürlich eine schlechte Sache ist. Also, wo ist das Problem? Die erste Zeile muss in Ordnung sein, und die dritte Zeile muss in Ordnung sein - Sie können jede Art von Obst zu List<Fruit> hinzufügen - so muss das Problem in der zweiten Zeile sein. Das ist verboten, um diese Art von Problem zu vermeiden.

Does diese Hilfe überhaupt?

+0

Das ist eine sehr coole Antwort, muss ich sagen. – Ziggy

6

Wie angegeben, können Sie nicht in 10 umwandeln, Sie können jedoch in ArrayList<? extends Card> umwandeln. Oder besser nutzen List<? extends Card> als Rückgabewert, da Sie wahrscheinlich auf der Arraylist Implementierung ohnehin nicht verlassen:

protected ArrayList<? extends Card> getCardBox(); 

Was Ihre Frage in dem Kommentar, sollte die Konstruktion arbeitet, wie Sie beschrieben: List<? extends Card> list = new ArrayList<Card>();. Sie haben wahrscheinlich die Liste zu füllen, so dass die Methode ist wahrscheinlich so etwas wie folgt aus:

protected ArrayList<? extends Card> getCardBox() { 
    List<Card> list = new ArrayList<Card>(); 
    list.add(pokerCard1); 
    list.add(pokerCard2); 
    return java.util.Collections.unmodifiableList(list); 
} 
+0

Das hat sehr geholfen, danke. –

4

Eine Möglichkeit, dass zuerst Arraylist durch Gießen zu tun:

ArrayList<Card> cards= (ArrayList<Card>)(ArrayList<?>) (PokerCardObject);