восходящий из Списка <подкласс> для Списка <суперкласс> с помощью Списка <?>

У меня есть класс A, и класс B расширяет A

В другом классе C у меня есть поле

private List<B> listB;

Теперь, по некоторой необычной причине, я должен реализовать этот метод в C

public List<A> getList();

Я пытался сделать так, вынуждая восходящее из listB поля Перечислить<A> с помощью Списка<?> бросок:

public List<A> getList(){
    return (List<A>)(List<?>)listB;
}

Клиенты должны сделать

List<A> list = getList();
for(A a:list){
    //do something with a
}

Я сделал некоторый тест, и это кажется работой правильно, но честно я не уверен во всех возможных последствиях.

Это решение правильно? И действительно ли это - лучшее решение?

Спасибо за Ваши ответы.

14
задан Max S 9 July 2010 в 12:46
поделиться

2 ответа

Нет, это небезопасно. Клиент не должен иметь возможность выполнять

List<A> list = getList();

, потому что в противном случае они могли бы написать

list.add(new C()); // Where C extends A

Тогда исходный код, который знает о списке как List , будет иметь проблемы когда он пытается его использовать, предполагая, что каждый элемент совместим с B .

Вы можете либо обернуть исходный список, чтобы он был доступен только для чтения, либо заставить getList вернуть List , что означает, что клиенты все равно не смогут добавлять к нему элементы.

16
ответ дан 1 December 2019 в 13:21
поделиться

Проблема заключается в том, что клиенты могут невольно вставлять объекты A только в список более конкретных объектов B :

c.getList().add(new A());

Это приведет к всевозможным сбоям, когда ваш код попытается взять объект из списка, предполагая, что это B , но это не так.

Если ваша единственная цель - позволить клиенту перебирать список, лучше вместо этого выдать Iterable :

public Iterable<A> getAs() { return this.theListOfAs; }

Через этот Iterable , один может только проверять и удалять элементы, но не добавлять их.

Если вы хотите также отключить удаление, оберните List Iterable в свою собственную реализацию, выбрасывая UnsupportedOperationException при remove () Вызывается .

3
ответ дан 1 December 2019 в 13:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: