Question

Sorry, I thought this was an inheritance question: it was an ArrayList question all along!

Ok, my problem is more specific than I thought. So I have two families of classes. Cards, and Zones. Zones are boxes for holding card.

The first two subClasses of Zone, ZoneList and ZoneMap are meant to be two different ways of storing Cards. Further subclasses, such as Hand, and PokerHand, have their own specific ways of dealing with the cards they store.

Where it gets complicated is that Card also has subClasses, such as PokerCard, and that the subclasses of ZoneList and ZoneMap are meant to organize those.

So in ZoneList I have protected ArrayList<Card> cardBox; and in PokerHand I expected to be able to declare cardBox = new ArrayList<PokerCard>(); since PokerCard is a Card. The error I am getting is that I apparently can't cast between Card and GangCard when it comes to ArrayLists... So I was trying to fix this by just redeclaring cardBox as private ArrayList<PokerCard> cardBox; inside PokerHand, but that resulted in the hiding that was bugging up my program.

SO really, the question is about casting between ArrayLists? Java tells me I can't, so any ideas on how I can?

z.

Was it helpful?

Solution

If I understand you correctly, you should probably declare:

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

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

OTHER TIPS

Marc and kolstae have given good answers in terms of how to get around the problem, but I think it's worth explaining why your original code doesn't work.

To simplify matters, I tend to put the problem in terms of fruit. Suppose we have:

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

If this is allowed, we end up with an apple in a bunch of bananas, which is obviously a bad thing. So, where is the problem? The first line has to be okay, and the third line has to be okay - you can add any kind of fruit to List<Fruit> - so the problem has to be in the second line. That's what's prohibited, precisely to avoid this kind of issue.

Does that help at all?

First of all, it's usually better practice to use getter/setter methods than accessing properties directly, especially if you're going to be doing a lot of complicated inheritance.

As for the generics problem, you could try defining the cardBox getter in the superclass (or top-level interface/abstract class) as:

protected ArrayList<? extends Card> getCardBox();

That way you can ovverride it in subclasses and have them return a list of any type of subclass of Card.

One way to do that is by casting to ArrayList first:

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

Another alternatives without casting:

With streams:

ArrayList<Card> cards = pokerCardObjects.stream().collect(Collectors.toCollection(ArrayList::new);

Or creating a new ArrayList:

ArrayList<Card> cards = new ArrayList<>(pokerCardObjects);

As stated, you cannot cast ArrayList<PokerCard> to ArrayList<Card>, but you can cast ArrayList<PokerCard> to ArrayList<? extends Card>. Or better use List<? extends Card> as your return value, because you probably don't rely on the ArrayList implementation anyway:

protected ArrayList<? extends Card> getCardBox();

As for your question in the comment, the construction should work as you described: List<? extends Card> list = new ArrayList<Card>();. You probably have to fill your list, so the method is probably something like this:

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

This is going to depend on what the access control is on the Arraylist in Zonelist. My assumption from the debugger statement is that it is either unmarked, public, or protected. A subclass can "Hide" a parent class' variable it has access to by defining a variable with the same name. You can also use this keyword to refer to the particular object instance and super keyword to refer to the parent.

Here is a good link on basic access control in Java:

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

This you might also find helpful

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top