У меня есть класс Command, подобный следующему:
public class Command {
...
private String commandName;
private Object[] commandArgs;
...
public void executeCommand() {}
}
У меня также есть подкласс Command, AuthenticateCommand:
public class AuthenticateCommand extends Command {
...
@Override
public void executeCommand() {
...
}
}
Теперь представьте класс Server, у которого есть метод processCommand (команда command). Он принимает команду param, проверяет поле commandName и использует это имя для приведения команды к подклассу Command, отвечающему за реализацию логики команды. В этом примере вы можете использовать команду с именем команды «authenticate» и именем пользователя и pw, хранящимися в массиве commandArgs. processCommand () приведёт команду к AutheticateCommand и вызовет метод executeCommand (). Я пытаюсь сделать это с помощью следующего (commandMap - это просто карта, которая отображает имя_команды на имя класса разработчика):
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);
}
}
При вызове ImplementorClass.cast () генерируется исключение ClassCastException. Разве он не должен быть в состоянии понижать класс AuthenticateCommand таким образом?
UPDATE
Еще немного фона. Класс Server обрабатывает больше, чем просто AuthenticateCommands. В зависимости от проекта может быть любое количество подклассов Command. Я пытаюсь упростить кому-то, пишущему Клиент, передавать сериализованный объект Command только с именем и аргументами. Я мог бы заставить клиента «знать» об AuthenticateCommand и всех остальных, а затем сериализовать их и передать их, но это кажется неоптимальным, потому что единственное различие между подклассами - реализация executeCommand, которая не заботит клиента или знать о. Поэтому я просто хочу, чтобы Клиент передавал родительский класс и использовал данные в этом родительском классе для приведения его к соответствующему подклассу.
Полагаю, я мог бы использовать newInstance () вместо приведения и просто создать новый объект, но это кажется расточительным. Я полагаю, что мог бы также отказаться от концепции подклассов, обрабатывающих логику, и переместить их в методы, а затем processCommand вызовет соответствующий метод. Хотя и это мне не по зубам.