简体   繁体   中英

Java: Subclass of the type in a method signature

Ok. So I'm trying to set up a GUI for an application using the observer pattern. In standard fashion; if an Observable updates it calls the update method of all its observers, passing a ComponentUpdateEvent, as follows:

public interface Observable {
 ArrayList<Observer> observers = new ArrayList<Observer>();

 public void updateObservers();

 public void addObserver(Observer observer);

 public void removeObserver(Observer observer);
}

public interface Observer {
 public void update(ComponentUpdateEvent updateEvent);
}

public abstract class ComponentUpdateEvent {
 public abstract ComponentType getComponentType();
}

I have a number of different components, which implement Observable, in the 'model' side of the application. Each type of component has a seperate subclass of the Drawer class, which implements Observer, for rendering to a JPanel.

The problem is that I'm trying to make it so that when the update method of a Drawer subclass is called, that the updateEvent parameter passed can be a subclass of ComponentUpdateEvent.

However, obviously if I try and do this as follows:

 @Override
 public void update(ConsoleUpdateEvent updateEvent) throws Exception {
  if (this.componentType != updateEvent.get)) {
   throw new Exception("ComponentType Mismatch.");
  }
  else {
   messages = updateEvent.getComponentState(); 
  }
 }

I get the compiler error:

The method update(ConsoleUpdateEvent) of type ConsoleDrawer must override or implement a supertype method.

Because the method signature isn't the same. I can't seem to get around this problem without having seperate observer classes for each type of component, is it possible to solve this problem with generics? Any help would be appreciated.

Your interface has to declare that it throws Exception to solve your compiler error. The reason for this is that you don't pass a class type around, you pass the Observer interface around. So, if one class that implements Observable throws an exception, the calling class will not know about it unless the interface specifies it.

In your Observer interface, your update() method doesn't throw Exception and your ConsoleDrawer.update() does. The 2 aren't the same according to java.

Either you remove throw Exception on ConsoleDrawer or add the exception on the Observer interface.

In general, Java allows you to weaken the returned value when overriding a method, or strengthen the parameters. In this case, however, you are trying to weaken the parameter.

Maybe generics can help. I have to admit that I haven't tried the code below, this is just from memory:

You can try to use generics in the signature of the Observer interface:

public interface Observer<T>

or

public interface Observer<T extends ComponentUpdateEvent>

In addition to that, I'd revise the signature of Observable interface.

public void addObserver(Observer<T extends ComponentUpdateEvent> observer)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM