java:统一处理子类

java:统一处理子类,java,generics,reflection,Java,Generics,Reflection,假设我有这个: abstract class Command { static void run (String[]argv) {} } class Slice extends Command { static void run (String[]argv) {/* slicing code */} } class Dice extends Command { static void run (String[]argv) {/* dicing code */} } 我希望能够对命令

假设我有这个:

abstract class Command {
  static void run (String[]argv) {}
}
class Slice extends Command {
  static void run (String[]argv) {/* slicing code */}
}
class Dice extends Command {
  static void run (String[]argv) {/* dicing code */}
}
我希望能够对命令进行迭代,因此我写道:

Class<Command>[] commands = {Slice.class,Dice.class}; /* compile error */
for (Class<Command> c : commands) {
  if (some_string.equals(c.getName()) {
    c.getDeclaredMethod("run",String[].class).invoke(argv);
    return;
  }
}
当然,这是可以抑制的,但是,我想知道,有没有更优雅的解决方案


(当然,在C语言中,这可以通过包含两个元素的结构数组来实现:一个字符串和一个指向函数的指针)。

尝试将命令数组声明为
Class仅
command。Class
属于
Class
类型。它的所有子类型都是
Class类型,我强烈建议您只需删除反射并使类成为实例(这样方法就不再是静态的),一切都将更加清晰和合理,然后你会发现这种设计允许你将来改进你的课程——如果你继续沿着这条路走下去,你将陷入一个充满伤害的世界(好吧,至少是一个充满伤害的小城市)

我喜欢反射在Java中是不平凡的,正因为如此,它让人们有点泄气,让他们重新思考自己的方法

请注意,您还将一些数据直接绑定到类名(代码构造)。我并不是说这是错的,我已经做过很多次了,它非常诱人和优雅——但最终我总是在某种程度上后悔。一些与你的类命名约定/规则不匹配的现实世界问题悄然出现

我只想使用这样的模式:Command.wants(一些_字符串),或者使用一个字符串到类实例的映射,它删除了整个循环,代码就变成了

myHashMap<Command>.get(some_string).run();
myHashMap.get(一些字符串).run();

无论如何,您的设计都不是实现此模式的好方法。在Java中,即使在不需要实例状态的情况下使用实例,也可以获得更清晰的代码:

命令 使用 (我也可能将命令存储在从命令名到实现的
HashMap
中,而不是搜索数组。)

Class[]命令={Slice.Class,Dice.Class};/*编译错误*/
不能在Java中创建泛型数组

因此,如果需要泛型集合,则必须使用集合框架中的某些类

e、 g


list为什么要使用类对象(和静态
run
方法)而不是类实例和实例
run
方法?我认为对于第二种方法,最好使
run
方法非静态。因为,查看代码片段很难判断它不是一个实例方法+1.@BheshGurung是的,run方法作为非静态方法更有意义(使用@DmitryBeransky提到的
Command
作为接口)。如果第二个命令中的方法是静态的,那么代码会正常工作吗?我认为Java中的静态方法调用是早期绑定的,这取决于变量的编译时类型。当然,在Java中无法清楚地表达这一点也可以被视为该语言的缺陷。(例如,我相信Obj-C确实允许您继承和重写静态方法。)也就是说,在这种情况下,使用反射是次优设计。
Class<? extends Command>[] commands = {Slice.class,Dice.class};
for (Class<? extends Command> c : commands) {
  if (some_string.equals(c.getName()) {
    c.getDeclaredMethod("run",String[].class).invoke(argv);
    return;
  }
}
Command[] commands = {new Slice(), new Dice()};
for (Command cmd : commands) {
  if (some_string.equals(cmd.getClass().getName())) {
    cmd.run (argv);
    return;
  }
}
myHashMap<Command>.get(some_string).run();
interface Command {
    void run(String[] args);
}

class Slice implements Command {
    void run(String[] args) { /* slices */ }
}

class Dice implements Command {
    void run(String[] args) { /* dices */ }
}
Command[] = {new Slice(), new Dice()};
for (Command c : commands) {
    if (someString.equals(c.getClass().getName())) {
        c.run(args);
        return;
    }
}
Class<Command>[] commands = {Slice.class,Dice.class}; /* compile error */
List<Class<? extends Command>> commandList = new ArrayList<Class<? extends Command>>();
commandList.add(Slice.class);
commandList.add(Dice.class);
for(Class<? extends Command> command : commandList) {
    Method runMethod = command.getDeclaredMethod("run", String[].class);
    runMethod.setAccessible(true);
    runMethod.invoke(null, new Object[]{null});    
}