Приведение между списками массивов в 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? Java говорит мне, что я не могу, так что есть идеи, как я могу?

z.

Подумать об этом! Другая ситуация, которая, на мой взгляд, похожа, - это когда я вызываю getElementAt (); и он возвращает мне GImage, с которым я не могу обращаться как с GImage! Java вскакивает, когда я пытаюсь вызвать GImage.getName (); или что-то в этом роде, потому что это не изображение, а объект ...!

Ziggy 11.12.2008 09:19
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
1
40 564
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

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

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

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

Я не думаю, что это проблема контроля доступа - это общая проблема дисперсии.

Jon Skeet 11.12.2008 10:49

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

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

protected ArrayList<? extends Card> getCardBox();

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

Ах! Я не знал, что смогу это сделать: это здорово! Спасибо!

Ziggy 11.12.2008 10:11

При использовании этого <? extends Card> thingy, как мне инициализировать ArrayLists? просто старый ящик = новый ArrayList <Card> (); возвращает мне ошибку? ...

Ziggy 11.12.2008 12:08

В подклассе вы должны создать экземпляр List как свойство с 'private final List <PokerCard> cardBox = new ArrayList <PokerCard> ()', этот список будет возвращен методом getCardBox.

boutta 11.12.2008 12:57
Ответ принят как подходящий

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

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

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

О чувак! Это тоже здорово. Я полностью думал: «Было бы здорово, если бы я знал, как передавать типы в качестве параметров ...», и теперь я полностью понимаю! Друг!

Ziggy 11.12.2008 10:12

Если вы собираетесь сделать ZoneList универсальным, вы можете инициализировать cardBoard в списке зон: List <T> cardBox = new ArrayList <T> ();

Jon Skeet 11.12.2008 10:50

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

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

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

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

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

Как уже говорилось, вы не можете преобразовать 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);
}

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

Другие вопросы по теме