Java: Subclass of the type in a method signature
Ok. So I开发者_如何学Go'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)
精彩评论