Приведение между ArrayLists в Java

Извините, я думал, что это вопрос наследования: это был вопрос ArrayList с самого начала!

Хорошо, моя проблема более конкретна, чем я думал. Итак, у меня есть две семьи классов. Карты и зоны. Зоны - это коробки для хранения карты.

Первые два подкласса Zone, ZoneList и ZoneMap предназначены для двух разных способов хранения карт. Другие подклассы, такие как Hand и PokerHand, имеют свои особые способы работы с картами, которые они хранят.

Ситуация усложняется тем, что у Card также есть подклассы, такие как PokerCard, и что подклассы ZoneList и ZoneMap предназначены для их организации.

Так что в ZoneList у меня есть, protected ArrayList<Card> cardBox;а в PokerHand я ожидал, что смогу объявить, cardBox = new ArrayList<PokerCard>();поскольку PokerCard - это Карта. Ошибка, которую я получаю, заключается в том, что я, очевидно, не могу разыграть между Card и GangCard, когда дело доходит до ArrayLists ... Так что я пытался это исправить, просто изменив привязку cardBox как private ArrayList<PokerCard> cardBox;внутри PokerHand, но это привело к скрытию, которое вызывало ошибку моя программа

ТАК действительно, вопрос о кастинге между ArrayLists? Ява говорит мне, что я не могу, так что есть идеи, как я могу?

г.

11.12.2008 06:09:35
Подумать об этом! Другая ситуация, на мой взгляд, похожа, когда я вызываю getElementAt (); и это возвращает мне изображение, которое я не могу рассматривать как изображение! Когда я пытаюсь вызвать GImage.getName (), Java получает все в свои руки; или что-то, потому что это не изображение, это объект ...!
Ziggy 11.12.2008 06:19:25
6 ОТВЕТОВ
РЕШЕНИЕ

Если я вас правильно понимаю, вам, вероятно, следует заявить:

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

public class PokerHand extends ZoneList<PokerCard> {
   public PokerHand() {
      cardBox = new ArrayList<PokerCard>();
   }
}
12
11.12.2008 07:10:18
О чувак! Это тоже здорово. Я полностью думал: «Разве не было бы замечательно, если бы я знал, как передавать типы в качестве параметров ...», и теперь я полностью согласен! Друг!
Ziggy 11.12.2008 07:12:59
Если вы собираетесь сделать обобщенный ZoneList, вы можете инициализировать cardBox в ZoneList: List <T> cardBox = new ArrayList <T> ();
Jon Skeet 11.12.2008 07:50:12

Это будет зависеть от того, в каком контроллере доступа находится Arraylist Zonelist. Мое предположение из заявления отладчика состоит в том, что он либо не помечен, либо общедоступен, либо защищен. Подкласс может «скрыть» переменную родительского класса, к которой он имеет доступ, определив переменную с тем же именем. Вы также можете использовать thisключевое слово для ссылки на конкретный экземпляр объекта и superключевое слово для ссылки на родителя.

Вот хорошая ссылка на базовый контроль доступа в Java:

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

Это вы также можете найти полезным

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

1
11.12.2008 06:32:01
Я не думаю, что это проблема контроля доступа - это общая проблема дисперсии.
Jon Skeet 11.12.2008 07:49:02

Прежде всего, обычно лучше использовать методы getter / setter, чем прямой доступ к свойствам, особенно если вы собираетесь выполнять много сложного наследования.

Что касается общей проблемы, вы можете попробовать определить метод получения cardBox в суперклассе (или интерфейс / абстрактный класс верхнего уровня) как:

protected ArrayList<? extends Card> getCardBox();

Таким образом, вы можете переопределить его в подклассах и заставить их возвращать список любого типа подкласса Card.

10
11.12.2008 07:09:34
Ах! Я не знал, что смогу сделать это: это здорово! Спасибо!
Ziggy 11.12.2008 07:11:54
При использовании этого <? extends Card> что нужно, чтобы инициализировать ArrayLists? просто старая коробка = новый ArrayList <Card> (); возвращает мне ошибку? ...
Ziggy 11.12.2008 09:08:08
В подклассе вы должны создать экземпляр List как свойство с 'private final List <PokerCard> cardBox = new ArrayList <PokerCard> ()', этот список будет возвращен методом getCardBox.
boutta 11.12.2008 09:57:15

Марк и kolstae дали хорошие ответы с точки зрения того, как обойти проблему, но я думаю, что стоит объяснить, почему ваш оригинальный код не работает.

Чтобы упростить дело, я склонен ставить проблему с точки зрения фруктов. Предположим, у нас есть:

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

Если это разрешено, мы получаем яблоко в куче бананов, что явно плохо. Так в чем же проблема? Первая строка должна быть в порядке, а третья строка должна быть в порядке - вы можете добавить любой вид фруктов List<Fruit>- таким образом, проблема должна быть во второй строке. Это то, что запрещено, именно для того, чтобы избежать такого рода проблем.

Это помогает вообще?

19
11.12.2008 07:23:07

Как уже говорилось, вы не можете бросить 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);
}
6
11.12.2008 09:43:59

Один из способов сделать это - сначала привести к 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);
8
17.12.2018 17:00:28