2008-12-11 12 views
8

Lo siento, pensé que esta era una pregunta de herencia: ¡era una pregunta de ArrayList desde el principio!Casting entre ArrayLists en Java

Bien, mi problema es más específico de lo que pensaba. Entonces tengo dos familias de clases. Tarjetas y Zonas Las zonas son cajas para sostener la tarjeta.

Las dos primeras subclases de Zone, ZoneList y ZoneMap están destinadas a ser dos formas diferentes de almacenar tarjetas. Otras subclases, como Hand y PokerHand, tienen sus propias formas específicas de tratar con las cartas que almacenan.

Donde se complica es que la Tarjeta también tiene subclases, como PokerCard, y que las subclases de ZoneList y ZoneMap están destinadas a organizarlas.

Así que en ZoneList tengo protected ArrayList<Card> cardBox; y en PokerHand esperaba poder declarar cardBox = new ArrayList<PokerCard>(); ya que PokerCard es una carta. El error que estoy obteniendo es que aparentemente no puedo transmitir entre Card y GangCard cuando se trata de ArrayLists ... Así que estaba tratando de arreglar esto simplemente redeciendo cardBox como private ArrayList<PokerCard> cardBox; dentro de PokerHand, pero eso resultó en el ocultamiento que estaba molestando mi programa

SO realmente, la pregunta es sobre el lanzamiento entre ArrayLists? Java me dice que no puedo, entonces ¿alguna idea sobre cómo puedo?

z.

+0

Ahora que lo pienso de ella! Otra situación que creo que es similar es cuando llamo a getElementAt(); y me devuelve una GImage, ¡que no puedo tratar como una GImage! Java se levanta de brazos cuando trato de llamar a GImage.getName(); o algo así, porque no es una imagen es un objeto ...! – Ziggy

Respuesta

11

Si he entendido bien, es probable que debe declarar:

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

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

¡Oh hombre! Eso también es genial. He estado pensando "¿no sería genial si supiera cómo pasar los tipos como parámetros ..." y ahora lo hago totalmente? ¡Amigo! – Ziggy

+1

Si va a hacer genérico ZoneList, puede inicializar cardBox en ZoneList: List cardBox = new ArrayList (); –

1

Esto dependerá de qué control de acceso se encuentre en el Arraylist en Zonelist. Mi suposición de la declaración del depurador es que no está marcada, es pública o está protegida. Una subclase puede "Ocultar" una variable de clase principal a la que tiene acceso definiendo una variable con el mismo nombre. También puede usar la palabra clave this para referirse a la instancia del objeto particular y la palabra clave super para referirse al padre.

Aquí es un buen enlace en el control de acceso básico en Java:

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

Esto también podría resultar útil

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

+0

No creo que sea un problema de control de acceso: es un problema de varianza genérica. –

10

En primer lugar, por lo general es mejor la práctica de usar métodos getter/setter que accediendo directamente a las propiedades, especialmente si vas a estar haciendo una gran cantidad de herencia complicada.

En cuanto al problema de los genéricos, que podría intentar definir el captador cardbox en la superclase (o interfaz/clase abstracta de nivel superior) como:

protected ArrayList<? extends Card> getCardBox(); 

De este modo puede ovverride en subclases y tenerlos devolver una lista de cualquier tipo de subclase de la Tarjeta.

+0

¡Ah! No sabía que podía hacer eso: ¡eso es genial! ¡Gracias! – Ziggy

+0

Al usar este thingy, ¿cómo debo proceder para inicializar ArrayLists? simplemente viejo cuadro = nueva ArrayList (); ¿me devuelve un error? ... – Ziggy

+1

En la subclase creará una lista como propiedad con 'private final List cardBox = new ArrayList ()' esta lista sería devuelta por el método getCardBox. – boutta

19

Marc y kolstae han dado buenas respuestas en términos de cómo evitar el problema, pero creo que vale la pena explicar qué el original el código no funciona

Para simplificar las cosas, tiendo a poner el problema en términos de fruta.Supongamos que tenemos:

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

Si esto se permite, nos encontramos con una manzana en un racimo de plátanos, lo que obviamente es una mala cosa. ¿Entonces, dónde está el problema? La primera línea tiene que estar bien, y la tercera línea tiene que estar bien, puede agregar cualquier tipo de fruta al List<Fruit>, por lo que el problema debe estar en la segunda línea. Eso es lo que está prohibido, precisamente para evitar este tipo de problema.

¿Eso ayuda en absoluto?

+0

Esta es una respuesta muy buena, tengo que decir. – Ziggy

6

Como se indicó, no se puede convertir ArrayList<PokerCard> en ArrayList<Card>, pero puede convertir ArrayList<PokerCard> en ArrayList<? extends Card>. O mejor utilizar List<? extends Card> como su valor de retorno, porque es probable que no se basan en la aplicación de todas formas ArrayList:

protected ArrayList<? extends Card> getCardBox(); 

cuanto a su pregunta en el comentario, la construcción debe funcionar como se describe a continuación: List<? extends Card> list = new ArrayList<Card>();. Es probable que tenga que llenar su lista, por lo que el método es probablemente algo como esto:

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

Esto ayudó mucho, gracias. –

4

Una forma de hacerlo es mediante la fundición a ArrayList primera:

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