Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Java: преобразование между типами итераторов (интерфейс/класс реализации)?

Автор вопроса: user905686Ответов: 4

В классе у меня есть контейнер:

public class MyClass implements MyClassInterface {
  private LinkedList<OtherClass> list; //Need to use 'OtherClass' instead of 'OtherClassInterface here
  @Override
  public Iterator iterator() {
    return list.iterator; //Problem!
  }
}

Интерфейс:

public interface MyClassInterface {
  //Is
  public Iterator iterator();
  //Should be
  public Iterator<OtherClassInterface>();
}

Опять же, OtherClass также имеет интерфейс OtherClassInterface. Я хочу, чтобы интерфейсы использовались только теми, кто работает с кодом. Проблема в том, что я хочу использовать полный OtherClass внутри MyClass, но передать итератор поверх LinkedList<OtherClassInterface> вызывающей стороне MyClassInterface.iterator().

Я не мог преобразовать существующий LinkedList<OtherClass> в LinkedList<OtherClassInterface> внутри MyClass, чтобы вернуть нужный итератор.

Как справиться с такой ситуацией?

Редактировать

Причина, по которой я хочу такого поведения

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

Как уже упоминалось, другой разработчик хочет использовать оба интерфейса. Поверх высшего хочу предоставить итератор, дающий доступ к элементам нижнего интерфейса - но не к классу, реализующему интерфейс.

Дополнительные потребности

Я также хочу, чтобы возвращаемый итератор был "Итерируемым", т.е. чтобы я мог использовать конструкцию "для каждого". Это также возможно с раствором *wixwing*? Если возможно, я бы не хотел реализовывать собственный итератор - для меня это кажется не обязательным, потому что я просто хочу дать итератор элементам интерфейса вместо реализующего класса.

  • еще лучше, почему бы вам не объяснить, чего вы действительно хотите достичь? могут быть другие/лучшие способы? в конце концов, вероятно, есть больше решений этой проблемы, с которой вы столкнулись ant 17.05.2012

javainterfacetype-conversioniterator

Ответы

Ответ 1 · рейтинг 1 · Attila

Вы можете написать свою собственную реализацию Iterator, которая преобразует интерфейс в конкретную реализацию при возврате из next().

Проблема с преобразованием List<OtherClass> в List<OtherClassInterface> заключается в том, что нет способа запретить пользователю результата преобразования помещать в список что-либо, кроме объектов OtherClass (конечно, эти элементы также должны реализовывать OtherClassInterface)

Ответ 2 · рейтинг 1 · waxwing

Можете ли вы определить интерфейс, как это?

public interface MyClassInterface {
    public Iterator<? extends OtherClassInterface>();
}

list.iterator() должно быть допустимым возвращаемым значением для этого метода, даже если список равен List<OtherClass>.

Ответ 3 · ant

Можно ли изменить интерфейс?

public interface MyClassInterface<T> {
    public Iterator<T> iterator();
}

Вы всегда можете реализовать свой собственный итератор:

public class MyClass implements MyClassInterface<T> {
  private LinkedList<T> list;

  @Override
  public Iterator iterator() {
   return new Iterator<T>() {
            int index;

            public boolean hasNext() {
                return index < list.size();
            }

            public T next() {
                return list.get(index++);
            }

            public void remove() {

            }
        };
  }
}

не проверял код

Ответ 4 · user905686

Интерфейс можно определить следующим образом:

public interface MyClassInterface {
    public LinkedList<? extends OtherClassInterface> list();
}

Тогда реализация должна выглядеть так:

@Override
public LinkedList<OtherClass> list() {
    return list; //this is the container of type LinkedList<OtherClass>
}

Это имеет следующие преимущества:

  • При вызове list() объектом OtherClass вы получите LinkedList<OtherClass>
  • При вызове list() объектом OtherClassInterface вы получите LinkedList<OtherClassInterface>
  • Возвращаемое значение каждого может использоваться в цикле for-each.
  • Итератор можно получить list().iterator()

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы