car*_*nun 8 java generics parameters overriding subclass
所以我之前问过这个问题,但我在代码中遇到了一个错误,大多数人都接受了这个问题,而不是问题本身.
无论如何,我试图覆盖类中的接口方法.但是,我希望覆盖方法中的参数类型是overriden方法中定义的参数类型的子类.
界面是:
public interface Observer {
public void update(ComponentUpdateEvent updateEvent) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
虽然覆盖此方法的类是:
public class ConsoleDrawer extends Drawer {
//...
@Override
public void update(ConsoleUpdateEvent updateEvent) throws Exception {
if (this.componentType != updateEvent.getComponentType()) {
throw new Exception("ComponentType Mismatch.");
}
else {
messages = updateEvent.getComponentState();
}
}
//...
}
Run Code Online (Sandbox Code Playgroud)
ConsoleUpdateEvent是ComponentUpdateEvent的子类.
现在,我可以让ConsoleDrawer中的update()方法将ComponentUpdateEvent作为参数,然后将其转换为ConsoleUpdateEvent,但如果可能的话,我正在寻找一个更优雅的解决方案.任何帮助,将不胜感激.谢谢.
你不能.这不是埃菲尔.问题是您可以使用接口以不兼容的类型调用实现方法.因此不允许使用协变参数.也不允许使用逆变参数,但更容易提供过载.允许协变返回类型(从1.5开始).
您可以参数化界面:
public interface Observer<T extends ComponentEvent> {
void update(T event) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
或者,使用更有意义的界面:
public interface ConsoleObserver {
void update(ConsoleEvent event) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)
你可以尝试以下方法。如果编译器知道您将调用第一个方法而不是第二个方法,则 @Deprecated 会生成警告。
@Override @Deprecated
public void update(ComponentUpdateEvent updateEvent) {
// throws a ClassCastException if its not the right type.
update((ConsoleUpdateEvent) updateEvent);
}
public void update(ConsoleUpdateEvent updateEvent) {
messages = updateEvent.getComponentState();
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句:你不应该只在所有事情上都抛出异常。这当然不是最佳实践。
编辑:我已经针对这个问题实现了一个不同的解决方案,该解决方案与 OSGi 配合良好,但可以在任何地方工作。
观察者向代理注册自己,并期望找到带有注释的方法,例如 ObserverCallback。
例如
public class ConsoleDrawer extends Drawer {
@ObserverCallback
public void onConsoleUpdateEvent(ConsoleUpdateEvent updateEvent) {
messages = updateEvent.getComponentState();
}
}
public class DeviceDrawer extends Drawer {
@ObserverCallback
public void onDeviceUpdateEvent(DeviceUpdateEvent updateEvent) {
// do something.
}
}
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,代理找到带有 @ObserverCallback 的方法,该方法采用一个参数。这是 Broker 将传递的唯一类型。第二类期望不同的类型。观察者可以有多种方法/类型,允许他们以适合该类型的不同方法处理不同的消息。您还知道您永远不会收到您不期望的数据类型。