2016-05-28 94 views
0

注意:我真的不知道如何問我的問題,所以我的標題可能沒有任何公正。如何通過ArrayList <SubClass> as ArrayList <BaseClass>

我開始寫一個RSS解析器。我希望用戶能夠指定他們想要的信息,並且我的parseInnerXmlByTag方法將返回該類型的ArrayList。問題是不同的標籤具有不同的屬性,這意味着我將不得不爲每種類型的標籤(「項目」,「通道」,「條目」...)創建類別。所以我決定創建一個空的RSSElement類。然後我創建了一個擴展它的RSSItem類。所以我的parseInnerXmlByTag現在返回一個ArrayList < RSSElements>。 我的目標是讓用戶只調用一個方法來指定他們想要的信息。假設他們指定了「item」,該方法應該返回ArrayList < RSSItem>。

但是像這樣的生產線將無法工作,因爲這兩種類型不techically有關係:

ArrayList<RSSElement> data = (method returning ArrayList<RSSItem>) 

我有麻煩纏繞我的頭周圍通配符和亞型,所以我在想,如果有人可以看看我到目前爲止給我的想法。這裏是我的代碼

public class RSSParser { 
public static ArrayList<RSSElement> parseInnerXmlByTag(String in, String tag) 
     throws XmlPullParserException, IOException{ 
    ArrayList<RSSElement> data = new ArrayList<>(); 
    StringReader input = new StringReader(in); 
    try{ 
     XmlPullParser parser = Xml.newPullParser(); 
     parser.setInput(input); 
     parser.nextTag(); 
     data = readFeed(parser, tag); 
    } 
    finally { 
     input.close(); 
     return data; 
    } 
} 

/* 
Returns an ArrayList of parsed RSSElements specified by "tag" 
*/ 
private static ArrayList<RSSElement> readFeed(XmlPullParser parser, String tag) 
     throws XmlPullParserException, IOException{ 
    ArrayList<RSSElement> data = new ArrayList<>(); 
    int event = parser.getEventType(); 

    //Parse until input is consumed 
    while(event != XmlPullParser.END_DOCUMENT){ 
     switch (event){ 
      case XmlPullParser.START_TAG: 
       if(parser.getName().equalsIgnoreCase(tag)){ 
        RSSItem item = RSSItem.processItem(parser); 
        data.add(RSSItem.processItem(parser)); 
       } 
       break; 
     } 
     event = parser.next(); 
    } 
    return data; 
} 

public static abstract class RSSElement{ 
    //Private constructor prevents instantiation 
    private RSSElement(){} 
} 

public static class RSSItem extends RSSElement{ 
    String title = ""; 
    String description = ""; 
    public RSSItem(String t, String d){ 
     title = t; 
     description = d; 
    } 

    @Override 
    public String toString() {...} 

    /* 
    Parses an RSS item tag into a container RSSItem (ONLY GRABS TITLE RIGHT NOW) 
    */ 
    protected static RSSItem processItem(XmlPullParser parser) 
      throws XmlPullParserException, IOException{ 
     String currentTag = ""; 
     String title = ""; 
     /* 
      while end tag hasn't been reached yet: 
      reaching the end tag means parser.getEventType == END_TAG && parser.getName = tag 
     */ 
     while(!(parser.next() == XmlPullParser.END_TAG && parser.getName().equalsIgnoreCase("item"))){ 
      Log.i("rssparser", "process entry"); 
      if(parser.getEventType() == XmlPullParser.START_TAG){ 
       currentTag = parser.getName(); 
      } 
      else if(parser.getEventType() == XmlPullParser.TEXT && currentTag.equalsIgnoreCase("title")){ 
       title = parser.getText(); 
       break; 
      } 
     } 
     return new RSSItem(title, description); 
    } 
} 
} 

現在這段代碼完成並返回ArrayList。另外我知道它是根據我的日誌正確解析RSSItems。 但這裏是我用它(又名原因,我在這裏發帖)

   @Override 
       public void onResponse(String response){ 
        ArrayList<? extends RSSParser.RSSElement> items = null; 
        try { 
         items = RSSParser.parseInnerXmlByTag(response, "entry"); 
        }... 

        if(items != null) { 
         for(int i = 0; i < items.size(); i++){ 
          //****DOESNT WORK**** 
          redditOutputTextView.append(items.get(i).title + "\n"); 
         } 
        } 
        else redditOutputTextView.setText("Items null"); 
       } 

該行存在顯然無法工作,因爲它不知道它的RSSItems的數組。所以希望有人能夠弄清楚我想要做什麼並提出一些建議。

回答

2

能否請您替換下面的代碼片段

//****WORKS**** 
Object obj=items.get(i); 
if(obj instanceof RSSItem){ 
    RSSItem rssItem = (RSSItem)obj; 
    redditOutputTextView.append(rssItem .title + "\n"); 
} 

和看到的結果?

+0

已修復它!那麼這個和我注意到的事實的結合,我在一行中調用了processItem方法兩次,可能創建了空對象。謝了哥們。 – sadelbrid

0

變化

ArrayList<? extends RSSParser.RSSElement> items = null; 

ArrayList<RSSParser.RSSElement> items = null; 

基本上,你現在有可以採取的RSSElement

任何子類的項目的舊是一個列表,可能只需要一個列表從RSSElement派生的某些類的項目,並且由於您使用了通配符,因此該類型可能是任何內容,因此編譯器不知道。您可以撥打get並使用它,因爲您知道元素的超類:RSSElement。請參閱this answer。通過下面的語句

//****DOESNT WORK**** 
redditOutputTextView.append(items.get(i).title + "\n"); 

+0

但是說我的方法返回ArrayList 並把它放在項目中,我將如何訪問RSSItem屬性? – sadelbrid

+0

您將最終需要檢查事物的類型,因此要麼執行instanceof樹,要麼創建抽象類的方法 –

0

您可以正餐返回樂趣這樣的代碼:

public static List<? extends Parent> test2(){ 
     List<Parent> parents = new ArrayList<Parent>(); 
     parents.add(new Son1()); 
     return parents; 
} 

,並獲得名單如下:

List<? extends Parent> parents = test2(); 

和OBV,CLSS SON1()擴展父。

相關問題