我正在使用约书亚的基于文本的菜单系统的修改版本,我试图找出如何使用反射来创建从类声明的子类的项目列表。因为不同的菜单项使用不同的参数来操作底层数据,所以我在泛化它们的实例化时遇到了问题。
例如,任务是创建一个自定义链表,因此菜单选项将由Print
, Insert
, Save
, Quit
等组成。打印和插入只需要对链表的引用,以便解析输入并调用链表中的适当函数。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
总是接受单个对象作为参数,我可以在调用getConstructor
和newInstance
时做出这样的假设。之后,我将把它留给特定的类来将Object转换成有用的东西,以便它们可以从中提取on数据。
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
,我希望保持尽可能简单。有没有办法改进这个解决方案?
不完全是答案,
但由于我通常不太喜欢反射,这里有另一个想法:
您可以将data
和file
添加到您的基类MenuItem
中,并将它们留在不适用的null
中。
嗯。如果你在不需要数据的情况下有参数而忽略它们会发生什么?