8

抱歉,我认为这是一个继承问题:一直是一个 ArrayList 问题!

好的,我的问题比我想象的更具体。所以我有两个班级。卡片和区域。区域是存放卡片的盒子。

Zone 的前两个子类 ZoneList 和 ZoneMap 是存储卡片的两种不同方式。其他子类,例如 Hand 和 PokerHand,有自己特定的方式来处理它们存储的牌。

复杂之处在于 Card 也有子类,例如 PokerCard,而 ZoneList 和 ZoneMap 的子类旨在组织这些子类。

所以在 ZoneList 我有protected ArrayList<Card> cardBox;,在 PokerHand 我希望能够声明cardBox = new ArrayList<PokerCard>();,因为 PokerCard 是一张卡片。我得到的错误是,当涉及到 ArrayLists 时,我显然无法在 Card 和 GangCard 之间进行转换......所以我试图通过private ArrayList<PokerCard> cardBox;在 PokerHand 中重新声明 cardBox 来解决这个问题,但这导致了隐藏的问题我的程序。

所以真的,问题是关于 ArrayLists 之间的转换?Java告诉我我不能,所以有什么想法可以吗?

z。

4

6 回答 6

19

Marc 和 kolstae 就如何解决该问题给出了很好的答案,但我认为值得解释为什么您的原始代码不起作用。

为了简化问题,我倾向于将问题放在水果方面。假设我们有:

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

如果允许这样做,我们最终会得到一堆香蕉中的一个苹果,这显然是一件坏事。那么,问题出在哪里?第一行必须没问题,第三行必须没问题——你可以添加任何种类的水果List<Fruit>——所以问题必须在第二行。这就是被禁止的,正是为了避免这种问题。

这些帮助有用?

于 2008-12-11T07:23:07.030 回答
12

如果我对您的理解正确,您可能应该声明:

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

public class PokerHand extends ZoneList<PokerCard> {
   public PokerHand() {
      cardBox = new ArrayList<PokerCard>();
   }
}
于 2008-12-11T07:10:18.320 回答
11

首先,使用 getter/setter 方法通常比直接访问属性更好,尤其是当您要进行大量复杂的继承时。

至于泛型问题,您可以尝试将超类(或顶级接口/抽象类)中的 cardBox getter 定义为:

protected ArrayList<? extends Card> getCardBox();

这样,您可以在子类中覆盖它并让它们返回任何类型的 Card 子类的列表。

于 2008-12-11T07:09:34.237 回答
8

一种方法是先转换为 ArrayList:

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

没有铸造的另一种选择:

使用流:

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

或者创建一个新的 ArrayList:

ArrayList<Card> cards = new ArrayList<>(pokerCardObjects);
于 2014-08-10T22:11:42.860 回答
7

如前所述,您不能ArrayList<PokerCard>转换为ArrayList<Card>,但可以ArrayList<PokerCard>转换为ArrayList<? extends Card>。或者更好地List<? extends Card>用作您的返回值,因为您可能无论如何都不依赖 ArrayList 实现:

protected ArrayList<? extends Card> getCardBox();

至于您在评论中的问题,构造应该按照您的描述工作:List<? extends Card> list = new ArrayList<Card>();. 您可能必须填写您的列表,因此该方法可能是这样的:

protected ArrayList<? extends Card> getCardBox() {
    List<Card> list = new ArrayList<Card>();
    list.add(pokerCard1);
    list.add(pokerCard2);
    return java.util.Collections.unmodifiableList(list);
}
于 2008-12-11T09:43:59.773 回答
1

这将取决于 Arraylist 中的访问控制是什么Zonelist。我对调试器语句的假设是它要么是未标记的,要么是公开的,要么是受保护的。子类可以通过定义具有相同名称的变量来“隐藏”它可以访问的父类变量。您还可以使用this关键字来引用特定对象实例和super关键字来引用父对象。

这是Java中基本访问控制的一个很好的链接:

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

这可能对您也有帮助

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

于 2008-12-11T06:32:01.580 回答