Приведение между ArrayLists в Java - PullRequest
8 голосов
/ 11 декабря 2008

Извините, я думал, что это вопрос наследования: это был вопрос 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? Ява говорит мне, что я не могу, так что есть идеи, как я могу?

г.

Ответы [ 6 ]

19 голосов
/ 11 декабря 2008

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

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

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

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

Помогает ли это вообще?

11 голосов
/ 11 декабря 2008

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

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

public class PokerHand extends ZoneList<PokerCard> {
   public PokerHand() {
      cardBox = new ArrayList<PokerCard>();
   }
}
10 голосов
/ 11 декабря 2008

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

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

protected ArrayList<? extends Card> getCardBox();

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

8 голосов
/ 11 августа 2014

Один из способов сделать это - сначала привести к 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);
6 голосов
/ 11 декабря 2008

Как сказано, вы не можете разыграть 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);
}
1 голос
/ 11 декабря 2008

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

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

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

Это также может оказаться полезным

http://java.sys -con.com / узел / 46344

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...