Я использую модифицированную версию системы текстового меню JosAH и пытаюсь выяснить, как использовать отражение для создания списка элементов из объявленных подклассами класса. Поскольку разные элементы меню используют разные параметры для манипулирования базовыми данными, у меня возникла проблема с обобщением их реализации.
Например, задание состояло в том, чтобы создать пользовательский связанный список, поэтому пункты меню будут состоять из 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 во что-то полезное, из чего они могут получить данные.
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
, который я надеялся сделать как можно более простым. Есть ли способ улучшить это решение?