Hey all,
I have a Command class like the following:
public class Command {
...
private String commandName;
private Object[] commandArgs;
...
public void executeCommand() {}
}
I also have a subclass of Command, AuthenticateCommand:
public class AuthenticateCommand extends Command {
...
@Override
public void executeCommand() {
...
}
}
Now imagine a class, Server, that has a method processCommand(Command command). It takes the command param, inspects the commandName field, and uses that name to cast the command to a subclass of Command responsible for implementing the command logic. In this example, you might have a Command with a commandName of "authenticate" and the username and pw stored in the commandArgs array. processCommand() would cast the Command to AutheticateCommand and invoke the executeCommand() method. I'm trying to accomplish this with the following (commandMap is just a Map that maps a commandName to its implementor class name):
public void processCommand(Command command) {
String commandName = command.getCommandName();
String implementorClassString = commandMap.get(commandName);
try {
Class implementorClass = Class.forName(implementorClassString);
Object implementor = implementorClass.cast(command);
Method method = implementorClass.getDeclaredMethod("executeCommand", null);
method.invoke(implementor);
} catch (ClassNotFoundException e) {
logger.error("Could not find implementor class: " + implementorClassString, e);
} catch (NoSuchMethodException e) {
logger.error("Could not find executeCommand method on implementor class: " + implementorClassString, e);
} catch (IllegalAccessException e) {
logger.error("Could not access private member/method on implementor class: " + implementorClassString, e);
} catch (InvocationTargetException e) {
logger.error("Could not invoke executeCommand method on implementor class: " + implementorClassString, e);
}
}
The call to implementorClass.cast() is throwing a ClassCastException. Shouldn't it be able to downcast to the AuthenticateCommand class in this manner?
UPDATE
Some more background. The Server class handles more than just AuthenticateCommands. There could be any number of Command subclasses, depending on the project. I'm trying to make it simple for someone writing a Client to pass a serialized Command object with just a name and arguments. I could force the client to "know about" AuthenticateCommand and all the others, and then serialize those and pass them, but that seems sub-optimal because the only difference between the subclasses is the implementation of executeCommand, which the client doesn't care or know about. So I just want a way to have the Client pass the parent class, and use data within that parent class to cast it to the appropriate subclass.
I suppose I could use newInstance() instead of cast and just create a new object, but that seems wasteful. I suppose I could also do away with the concept of subclasses handling the logic and move those into methods, and then processCommand would call the appropriate method. That feels janky to me as well, though.