2017-08-02 51 views
0

我正在尝试创建一个子类为Iterable的类。这与question类似。但是,我需要让列表中的对象成为特定类的子类,例如在我的例子下面的QObject。另外,我需要我的迭代器来实现与ListIterator接口相关的特定方法。如何让Java Iterable返回基类扩展通用的子类型

问题是,实现ListIterator接口的内部类在我的实现中没有“返回”基类属性QObject。我在做QueueListIterator泛型时出了点问题。

现在,如果我在示例代码中声明队列<QObject>它的作品。这必须提供允许迭代器获取正确类型所需的信息。但是,只要将它声明为Queue,即使基本泛型类型是QObject,并且Queue类中的其他方法也使用基本泛型类型。

所以,我的问题是为什么会发生这种情况,是否有一种方法来指定QueueListIterator来辨别基类型?

public class Queue<T extends QObject> implements Iterable<T> { 
     /** 
     * The list of items in the queue. 
     */ 
     protected List<T> myList; 

     // other methods and defs 

     public final Iterator<T> iterator() { 
      return (new QueueListIterator()); 
     } 

     public final ListIterator<T> listIterator() { 
      return (new QueueListIterator()); 
     } 

     private class QueueListIterator implements ListIterator<T> { 

      protected ListIterator<T> myIterator; 

      protected QueueListIterator() { 
       myIterator = myList.listIterator(); 
      } 

      @Override 
      public void add(T o) { 
       throw new UnsupportedOperationException("The method add() is not supported for Queue iteration"); 
      } 

      @Override 
      public boolean hasNext() { 
       return myIterator.hasNext(); 
      } 

      @Override 
      public boolean hasPrevious() { 
       return myIterator.hasPrevious(); 
      } 

      @Override 
      public T next() { 
       return myIterator.next(); 
      } 

      @Override 
      public int nextIndex() { 
       return myIterator.nextIndex(); 
      } 

      @Override 
      public T previous() { 
       return myIterator.previous(); 
      } 

      @Override 
      public int previousIndex() { 
       return myIterator.previousIndex(); 
      } 

      @Override 
      public void remove() { 
       throw new UnsupportedOperationException("The method remove() is not supported for Queue iteration"); 
      } 

      @Override 
      public void set(T o) { 
       throw new UnsupportedOperationException("The method set() is not supported for Queue iteration"); 
      } 
     } 
    } 

    // testing code 
    public static void test(){ 

      Queue q = new Queue(); 
      // put some stuff in the Queue 
      QObject r1 = new QObject(q.getTime(), "A"); 
      q.enqueue(r1); 
      QObject r2 = new QObject(q.getTime(), "B"); 
      q.enqueue(r2); 

      // Does not work! 
      // incompatible object types, Object cannot be converted to QObject in the for(:) construct 
      for (QObject qo : q) { 
       System.out.println(qo); 
      } 
    } 
+0

我编辑的问题有,因为我的第一篇错过了LT和GT的迹象。是的,队列 q确实提供了必要的类型信息。但是,我相信在声明队列时不必提供基本的泛型类型,如果我可以获得QObjects –

+1

这只是泛型使用中的一个问题。它应该是'队列 q =新队列()'。 –

+0

我了解队列作品。但是,如果我只是将队列声明为队列q = new Queue(),那么我的其他方法(未显示),如T removeFirst()将从声明中获取通用基类型QObject,因为他们知道类型T必须是QObject的子类型。但是,我无法让Iteratable做同样的事情。 –

回答

0

使用原始类型Queue是一样的使用Queue擦除。原因T removeFirst()允许您检索QObjectIterator.next()不是T removeFirst()Iterator<T> iterator()以不同的方式擦除。删除一个类型变量是删除其最左边界,所以T将被删除为QObject,但是删除参数化类型是该类型没有任何类型参数,因此Iterator<T>将被删除为Iterator。 (source

没有办法使用原始类型,而应该使用Queue<QObject>代替。在某些情况下,您也可以使用Queue<?>作为参考类型。 (见PECS。)

另见What is a raw type and why shouldn't we use it?

+0

这很有帮助,尽管令人失望。看起来合理的是,应该让我的内部类以我想要的方式意识到基本的泛型类型。但是,不应该使用原始类型,这表示我的基础对类型系统的误解。现在有点清楚了。 –

1

如果你声明●此方式: 队列<的QObject> q

+0

这是一条评论,而不是一个答案。 –

+0

它可以是一个答案,如果它工作 – user265732

+0

我认为这是一个评论,而不是一个答案。我原来的帖子已经指出,这将起作用。 –