Java:在覆盖方法时替换参数的子类/子类型?

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,但如果可能的话,我正在寻找一个更优雅的解决方案.任何帮助,将不胜感激.谢谢.

Tom*_*ine 8

你不能.这不是埃菲尔.问题是您可以使用接口以不兼容的类型调用实现方法.因此不允许使用协变参数.也不允许使用逆变参数,但更容易提供过载.允许协变返回类型(从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)


Pet*_*rey 2

你可以尝试以下方法。如果编译器知道您将调用第一个方法而不是第二个方法,则 @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 将传递的唯一类型。第二类期望不同的类型。观察者可以有多种方法/类型,允许他们以适合该类型的不同方法处理不同的消息。您还知道您永远不会收到您不期望的数据类型。