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

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

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*? Если возможно, я бы не хотел реализовывать собственный итератор - для меня это кажется не обязательным, потому что я просто хочу дать итератор элементам интерфейса вместо реализующего класса.


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


Ответы (4)


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

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

person Attila    schedule 17.05.2012

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

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

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

person waxwing    schedule 17.05.2012

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

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() {

            }
        };
  }
}

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

person ant    schedule 17.05.2012

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

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()
person user905686    schedule 14.06.2012