Универсальный обозреватель Java
У меня есть 2 объекта: Protocol
а также Server
, Первый уведомляет Server
с разными предметами и Server
следует выполнить действие в зависимости от типа объекта. Итак, идеальный вариант для меня это:
// Server.java
public Server implements IObserver {
public void onAction(ActionObjectOne o) {
//do magic
}
public void onAction(ActionObjectTwo o) {
//do magic
}
....
}
// Protocol.java
public Protocol extends AObservable {
// ....
notifyObservers(ActionObjectOne one);
// ...
}
Поэтому я решил, что это работа для наблюдателя.
public interface IObserver {
<T extends IAction> void onAction(T action);
}
public class Server implements IObserver {
@Override
public <AuthAction> void onAction(AuthAction action) {
// HERE IS A PROBLEM
}
}
public class AuthAction extends Action; // Action implements IAction - a flag-interface
Ошибки в Server
:
- Метод onAction (AuthAction) типа Server должен переопределить или реализовать метод супертипа.
- Параметр типа AuthAction скрывает тип AuthAction.
Итак, как реализовать мой "идеальный вариант" =)?
3 ответа
Вы можете сделать что-то вроде этого:
public void update(Observable o, Object arg) {
try {
Method update = getClass().getMethod("onAction", arg.getClass());
update.invoke(this, arg);
} catch (NoSuchMethodException e) {
LOGGER.error("No onAction for <" + arg.getClass().getSimpleName() + "> action.");
LOGGER.catching(e);
} catch (Exception e) {
LOGGER.catching(e);
}
}
and then:
public void onAction (AuthAction action) {
System.out.println("New user incoming!");
}
В следующем синтаксисе
public <AuthAction> void onAction(AuthAction action) {
выражение AuthAction
является переменной типа, а не аргументом типа. Код выше эквивалентен
public <T> void onAction(T action) {
Таким образом, вы можете увидеть, как ваш Server
класс не реализует IObserver
метод. Я бы вместо этого сделал IObserver
универсальный интерфейс и реализовать его так
public interface IObserver<T extends IAction> {
void onAction(T action);
}
class Server implements IObserver<AuthAction> {
@Override
public void onAction(AuthAction action) {
}
}
Это набор IAction
Конечный, неизменный и управляемый? Если это так, ваш наблюдатель больше похож на посетителя и требует перегрузки для каждого из известных действий.
Если набор IAction
s не все эти вещи, но звонящий знает, какой IAction
передается статически, ваш IObserver
Интерфейс, как определено, является правильным. То есть реализатор интерфейса (например, Server
) должен динамически реагировать на конкретные IAction
класс, используя любой из нескольких ужасных вариантов в Java, чтобы сделать это.
public interface IObserver {
void < T extends IAction > onAction( T action );
}
public class Server implements IObserver {
@Override public void < T extends IAction > onAction( T action ) {
// ugliness, e.g. if-ladders based on instanceof
}
}
Я не думаю, что это очень тебя покупает.
Если звонящий не знает, какой IAction
будет использоваться во время выполнения, тогда ваш единственный выбор
public interface IObserver {
void onAction( IAction action );
}
public class Server implements IObserver {
@Override public void onAction( IAction action ) {
// ugliness, e.g. if-ladders based on instanceof
}
}
чья реализация будет выглядеть так же, как в предыдущем примере.