Как вернуть интерфейс из метода

1

Вот мой метод. Я хочу вернуть набор строк из Java-метода. Я хотел бы, чтобы вызывающий код решил, хочет ли он реализовать эту коллекцию в виде Vector или LinkedList или ArrayList или что-то еще, что реализует интерфейс List.

public List<String> findAvailableLanguages() {
    Iterator<Map.Entry<String, String>> it = this.iterator();
    List<String> list = new ArrayList<String>();
    while (it.hasNext()) {
        Map.Entry<String, String> n = it.next();
        list.add(n.getKey());
    }

...

Однако я должен создать экземпляр конкретного объекта класса внутри метода для создания коллекции. Что я теперь верну, что будет совместимо с любым классом, который реализует List?

Это возможно?

  • 0
    Вы знакомы с generics ?
Теги:
methods
interface
return-type

3 ответа

4
Лучший ответ

Это более эффективно для вызывающих абонентов, если вы разрешаете List в процессе заполнения вместо того, чтобы инициировать ваш собственный. Это также сделает код, который легко тестируется с помощью блока, так как это делает шаблон, известный как Injection Dependency.

public List<String> populateWithAvailableLanguages(List<String> list) {
    Iterator<Map.Entry<String, String>> it = this.iterator();
    // List<String> list = new ArrayList<String>();
    while (it.hasNext()) {
        Map.Entry<String, String> n = it.next();
        list.add(n.getKey());
    }
}

Теперь реализация List может быть указана вызывающим:

List<String> availableLanguages = new ArrayList<>();
Localizer.populateWithAvailableLanguages(availableLanguages);
  • 1
    Я думаю, что лучше не возвращать список в этом случае (т.е. иметь тип возврата void), так как это создает путаницу. Также имя метода должно быть изменено на что-то вроде populateListWithAvailableLanguages, что дает понять, что список, переданный в аргументе, будет заполнен.
  • 0
    @ кодер: Отлично! На самом деле я не делал ничего, кроме копирования исходного кода и добавления битов, но ваши советы очень полезны для сохранения удобства сопровождения кода.
Показать ещё 2 комментария
1

Короче говоря, возврат типа объекта ArrayList, который может быть добавлен в любой другой тип объекта, который реализует List, невозможен. Элементы могут быть перемещены и добавлены к другому типу объекта, но сам тип коллекции не может быть отброшен.

Я объясню, почему. Когда ты говоришь,

List<String> list = new ArrayList<String>();

ссылочным типом "списка" является List, а тип объекта - ArrayList. Объект "list", который вы теперь используете, дает вам доступ ко всем методам интерфейса List, но не к другим методам, которые ArrayList имеет, хотя объект списка может их видеть (вроде сужения преобразования). Вы можете отбросить этот объект списка обратно к объекту ArrayList, и это сработает, потому что экземпляр списка в любом случае может видеть методы, которые ArrayList имел и, следовательно, отбрасывает это назад, будет работать (вроде как расширение преобразования обратно к исходной ширине).

Но если вы должны были передать его одному из других классов, реализующих интерфейс List, например LinkedList или Vector или Stack, что произойдет? Экземпляр списка не знает, как реализуются другие методы, присутствующие в LinkedList, Vector или Stack (поскольку они не находятся в ArrayList). Так что это вроде конверсии, где вы не знаете, что нужно делать. Поэтому он отбросит ошибку компилятора.

Расширяя это, вы можете видеть, если бы у вас было:

List<String> list = new LinkedList<String>();

теперь, приведение списка обратно в LinkedList будет работать, но не обратно в ArrayList.

0

Ваша подпись метода должна быть следующей:

Public Collection (? Super List) findAvailableLanguages () {}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню