2011-12-03 25 views
0

我正在使用JosAH's text-based menu system的修改版本,並試圖弄清楚如何使用反射來創建來自類聲明子類的項目列表。因爲不同的菜單項使用不同的參數來操縱底層數據,所以我在推廣它們的實例時遇到了一個問題。使用反射來構建基於文本的菜單

舉例來說,任務是創建一個自定義鏈接列表,因此菜單選項將包括PrintInsertSaveQuit等印刷和插入只是爲了分析輸入需要對鏈接列表的引用並在鏈接列表中調用相應的函數。 Save另外需要文件保存到Quit不需要任何額外的參數。

public class MenuList extends TextMenu { //TextMenu extends MenuItem 
    List<MenuItem> items; 

    public MenuList (Object data, File file) {} //calls fillList 

    //calls createList which fills a List<MenuItem> and copies it to this.items 
    protected void fillList(Object data, File file) { 
     this.items.addAll(createList(this.getClass(), ... args?)); 
    } 

    private static class MenuQuit extends MenuItem { 
     public MenuQuit() {} //does not need data 
    } 

    private static class MenuOne extends MenuItem { 
     public MenuOne(Object data) {} //manipulates data 
    } 

    private static class MenuTwo extends MenuItem { 
     public MenuOne(Object data) {} //also manipulates data 
    } 

    private static class MenuThree extends MenuItem { 
     //manipulates data and saves to file 
     public MenuThree(Object data, File file) {} 
    } 

    private static class NestedMenu extends MenuList { 
     //needs parameters to pass to it's own menuItems 
     public NestedMenu(Object data, File file) {}  
    } 
} 

public static List<MenuItem> createList(Class cls, ...args?) { 
    List<MenuItem> items = new ArrayList<MenuItem>(); 
    try { 
     Classes<?>[] param = { parse(args)? }; 
     Class<?>[] menuList = cls.getDeclaredClasses(); 

     for(Class<?> c : menuList) { 
      if(MenuItem.class.isAssignableFrom(c)) {//only adding the MenuItems 
       Constructor<?> ct = c.getConstructor(param); 
       Object menuItem = ct.newInstance(...args?); 
       items.add((MenuItem) menuItem); 
      } 
     } 
    } catch (Exception e) { } 
} 

有什麼辦法來概括createList,以便菜單項創建必要的參數?另外,由於我在這方面工作了多長時間,因此我完全接受這種可能性,即這是一個完全過度工程的解決方案,我應該刪除這個想法的大部分,或者可能是全部。

編輯:我不知道這是否是添加此信息 - 這是一個解決方案,我就一直在想最好的地方,並通過一些迴應和評論看完之後,它可能是正確的。如果MenuItem總是接受單個對象作爲參數,那麼我可以在撥打getConstructornewInstance時作出此假設。之後,我將它放在特定的類上,將Object投射到可以從中提取數據的有用的東西。

public class MenuItem { 
    Object data; 
    public MenuItem(Object data) { 
     this.data = data; 
     parseData(); 
    } 
    protected abstract void parseData(); 
} 

private static class MenuQuit extends MenuItem { 
    public MenuQuit(Object data) { super(data) } //nothing additional needed 
    protected void parseData() {} //does nothing 
} 

private static class MenuSave extends MenuItem { //as outlined above 
    private CustomLinkedList list; 
    private File saveFile; 
    public MenuSave(Object data) { 
     super(data); 
    } 

    //may be able to use reflection to generalize this 
    protected void parseData() { 
     this.list = ((MyCustomData) data).list; 
     this.saveFile = ((MyCustomData) data).saveFile; 
    } 
} 

public class MyCustomData { 
    public CustomLinkedList list; 
    public File saveFile; 
    public int otherData; 
    public MyCustomData(CustomLinkedList a, File b, int c) {} //assignment 
} 

我試圖避免這種方法,因爲它開始增加複雜性的子類MenuItems,我希望能保持儘可能簡單。有沒有辦法改進這個解決方案?

回答

0

不完全是一個答案,
但因爲我通常不喜歡這裏反射的大風扇是另一種思路:

您可以添加datafile到你的基類MenuItem,讓他們null他們在哪裏不適用。

+0

我曾經想過,但數據和文件只是例子。我後來可能會有MenuItem需要各種其他參數,我不太喜歡讓MenuItem依賴於它的子類。 – pLiKT

+0

一些框架提供了一個通用的(不是Java的意義上的)'Object',它可以保存你的回調函數所需的數據。那個怎麼樣? – DerMike

+0

我發佈的解決方案類似於您所提及的@DerMike原始問題嗎? – pLiKT

0

嗯。如果您在不需要數據並且忽略它們的情況下有爭論,會發生什麼?