Общая реализация Итератора в Java - PullRequest
3 голосов
/ 15 декабря 2011

У меня есть следующий дизайн: У меня есть абстрактный класс Instance, У меня есть класс Library, который расширяет Instance и У меня есть класс File, который также расширяет экземпляр

Я создал собственную реализацию связанного списка, и она определяется следующим образом:

public class List<T extends Instance> implements Iterable {
    //some other code here

     public Iterator iterator(){
         return new ListIterator(this);

}

теперь я создал класс

public class ListIterator<T extends Instance> implements Iterator<T> {
    private List thisList;
    private Node current;

    public ListIterator(List l){
        thisList=l;
        current=thisList.head.next;
    }
    @Override
    public boolean hasNext() {
        if(current==null)
            return false;
        return false;
    }

    @Override
    public T next() {
        Node temp=current;
        current=current.next;
        return temp.data;
    }
}

Где Node равно

public class Node<T extends Instance> {
    public Node<T> next;
    public Node<T> prev;
    public T data;

    public Node(T data,Node prev, Node next){
        this.data=data;
        this.prev=prev;
        this.next=next;
    }   
}

поэтому моя проблема заключается в следующем: строка return temp.data вызывает ошибку:

Несоответствие типов - невозможно преобразовать из экземпляра в T.

Что не так с этим кодом?

Ответы [ 2 ]

4 голосов
/ 15 декабря 2011

Я бы сказал, что Node.data - это ссылка на Instance объект? В этом случае компилятор не может автоматически изменить Instance на T, потому что даже если T является Instance объектом (T extends Instance), любой данный Instance может не быть T.

Учебник по Java Generics объясняет это: http://docs.oracle.com/javase/tutorial/extra/generics/subtype.html

Кроме того, в вашем классе List<T> вы должны указать Iterator и ListIterator как универсальные, используя Iterator<T> и ListIterator<T>, иначе компилятор не сможет правильно обрабатывать универсальные шаблоны. Ваша ссылка Node также должна быть общей: Node<T>

Следовательно, вы должны использовать

private Node<T> current;

и

public T next() {
    Node<T> temp=current;
    current=current.next;
    return temp.data;
}

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

1 голос
/ 30 апреля 2015

Никто не заметил ошибку:

public boolean hasNext() {
    if(current==null)
        return false;
    return false;
}

Это инвариант. Если я что-то упустил, итератор очень быстро вернет 0 элементов!

...