2013-02-24 59 views
1

的地圖我需要初始化一個連接對象的XML定義豆類外徑不同的類型。我有目錄結構:地圖不同類型

data \ 
|_ plant \ 
| |_ pine.xml 
| |_ cucumber.xml 
|_ animal \ 
| |_dog.xml 
| |_cat.xml 
|_ fungus \ 
... 

我想按順序將其存儲在兩級地圖中:第一級地圖包含第二級地圖。每個二級地圖都包含一種類型的對象(類植物/動物/真菌......)。每個類擴展了具有一些常用字段和方法(名稱/ getName()/ setName(),desc/getDesc()/ setDesc(),toString(),equals()等的Dict類。 ,以方便所有這些對象我想有工廠方法Dict.fabricateAll(創建)這裏的問題是:如何使他們有精確的類型參數創建第二級地圖,我不想HashMap的<字符串,快譯通>但HashMap的<字符串,植物>,HashMap的<字符串,動物>等

現在我有以下代碼:

public static Map<String, Map<String, ? extends Dict>> fabricateAll() { 
    File topDir = new File(Dict.defDir); 
    File[] subDirs = topDir.listFiles(); 
    Map<String, Map<String, ? extends Dict>> dicts = new HashMap<>(subDirs.length); 

    String type; 
    String handle; 
    Map<String, ? extends Dict> dict; 

    for (File subDir : subDirs) { 
     type = subDir.getName(); 
     File[] xmlFiles = subDir.listFiles(new FilenameFilter() {public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".xml"); }}); 
     dict = new HashMap<>(xmlFiles.length); 

     for (File defFile : xmlFiles) { 
      handle = defFile.getName(); 
      handle = handle.substring(0, handle.lastIndexOf('.')-1); 

      try { 
       Class c = Class.forName(type); 
       Constructor bob = c.getConstructor(Class.forName("java.lang.String")); 
       dict.put(handle, bob.newInstance(handle)); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
     dicts.put(type, dict); 
    } 
    return dicts; 
} 

但有一個與線的一個問題: dict.put(手柄,bob.newInstance(手柄));

錯誤消息:「方法把接口Map < K,V >不能被應用到給定的類型的要求:字符串,CAP#1實測值:字符串,對象

是的,這的newInstance()生成對象和或許應該有一些投,但到什麼?我不想只是「(字典)」在這裏,我更喜歡「(植物)」,「(動物)」 ......爲合適的。那怎麼辦?

+0

你返回一個'地圖<字符串,地圖<字符串?擴展Dict >>'。因此,客戶端代碼無法知道地圖是否包含Plant,Cat或其他內容。它只知道它們是Dict的實例。所以把它投給Dict,一切都會好起來的。也就是說,我不會使用反射來做到這一點,而是工廠(每種字典的一個工廠),這將允許做你想做的事情。 – 2013-02-24 17:36:58

+0

但是動物可以運行()而植物不能。如果我將它轉換爲Dict,我不可能首先調用run(),而不是手動投射到Animal。 至於辦法「每一個快譯通工廠」:你的意思是我應該在的,而不是調用每個快譯通亞型和公共靜態編造(字符串處理)'「bob.newInstance(句柄)」做: 字典。 put(handle,c.getMethod(「fabricate」,Class.forName(「java.lang.String」)))? 這給出了相同的錯誤。 – Forseti 2013-02-24 17:56:52

+0

當你有一個Map ',你無法知道地圖包含什麼。你所能做的就是測試這個值是植物還是動物的一個實例(使用'instanceof'),並將這個值轉換爲植物或動物。那麼你將Map作爲'Map '獲得了什麼,因爲你將它作爲'Map 返回?擴展Dict>'。你的工廠理念確實是一個解決方案。您將需要返回Plant或Animal(取決於類)的方法,並且您需要地圖的類型爲Map 或Map 類型,具體取決於在目錄中。 – 2013-02-24 18:04:24

回答

1

將對象轉換爲字典這是多態的好處 - 你不必引用特定的子類,你可以編寫代碼時只引用單個基類Dict,這會給你:

  • 一)鬆耦合 - 在特定的子類
  • B)Exetensibility沒有編譯時依賴 - 你可以添加的子類,而無需修改此代碼。

是的,有辦法實現你問什麼(大switch語句想到的),但沒有,我會推薦。