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




Это будет зависеть от того, какой контроль доступа находится в Arraylist в Zonelist. Мое предположение из оператора отладчика состоит в том, что он либо немаркирован, либо общедоступен, либо защищен. Подкласс может «скрыть» переменную родительского класса, к которой у него есть доступ, путем определения переменной с тем же именем. Вы также можете использовать ключевое слово this для ссылки на конкретный экземпляр объекта и ключевое слово super для ссылки на родительский объект.
Вот хорошая ссылка на базовый контроль доступа в Java:
http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
Это также может оказаться полезным
http://java.sys-con.com/node/46344
Я не думаю, что это проблема контроля доступа - это общая проблема дисперсии.
Прежде всего, обычно лучше использовать методы получения / установки, чем прямой доступ к свойствам, особенно если вы собираетесь выполнять много сложного наследования.
Что касается проблемы дженериков, вы можете попробовать определить геттер cardBox в суперклассе (или интерфейсе верхнего уровня / абстрактном классе) как:
protected ArrayList<? extends Card> getCardBox();
Таким образом, вы можете переопределить его в подклассах и заставить их возвращать список любого типа подкласса Card.
Ах! Я не знал, что смогу это сделать: это здорово! Спасибо!
При использовании этого <? extends Card> thingy, как мне инициализировать ArrayLists? просто старый ящик = новый ArrayList <Card> (); возвращает мне ошибку? ...
В подклассе вы должны создать экземпляр List как свойство с 'private final List <PokerCard> cardBox = new ArrayList <PokerCard> ()', этот список будет возвращен методом getCardBox.
Если я правильно вас понял, вам, вероятно, следует заявить:
public class ZoneList<T extends Card> {
protected List<T> cardBox;
}
public class PokerHand extends ZoneList<PokerCard> {
public PokerHand() {
cardBox = new ArrayList<PokerCard>();
}
}
О чувак! Это тоже здорово. Я полностью думал: «Было бы здорово, если бы я знал, как передавать типы в качестве параметров ...», и теперь я полностью понимаю! Друг!
Если вы собираетесь сделать ZoneList универсальным, вы можете инициализировать cardBoard в списке зон: List <T> cardBox = new ArrayList <T> ();
Марк и Колстае дали хорошие ответы о том, как обойти проблему, но я думаю, что стоит объяснить Зачем, что ваш исходный код не работает.
Чтобы упростить задачу, я обычно выражаю проблему в терминах фруктов. Предположим, у нас есть:
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);
Подумать об этом! Другая ситуация, которая, на мой взгляд, похожа, - это когда я вызываю getElementAt (); и он возвращает мне GImage, с которым я не могу обращаться как с GImage! Java вскакивает, когда я пытаюсь вызвать GImage.getName (); или что-то в этом роде, потому что это не изображение, а объект ...!