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
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);
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>();
}
}
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
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?
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);
}
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.