2017-08-02 18 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

我認爲這是一個評論,而不是一個答案。我原來的帖子已經指出,這將起作用。 –