Java: подкласс типа в сигнатуре метода

В порядке. Итак, я пытаюсь настроить графический интерфейс для приложения, используя шаблон наблюдателя. Стандартным способом; если Observable обновляет, он вызывает метод обновления всех своих наблюдателей, передавая ComponentUpdateEvent, как показано ниже:

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();
}

У меня есть несколько различных компонентов, которые реализуют Observable на «модельной» стороне приложения. Каждый тип компонента имеет отдельный подкласс класса Drawer, который реализует Observer для рендеринга в JPanel.

Проблема в том, что я пытаюсь сделать так, чтобы при вызове метода обновления подкласса Drawer переданный параметр updateEvent мог быть подклассом ComponentUpdateEvent.

Однако, очевидно, если я попытаюсь сделать это следующим образом:

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

Я получаю ошибку компилятора:

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

Потому что подпись метода не та. Я не могу обойти эту проблему, не имея отдельных классов наблюдателей для каждого типа компонентов, возможно ли решить эту проблему с помощью дженериков? Любая помощь будет оценена.


person carnun    schedule 09.12.2010    source источник


Ответы (3)


Ваш интерфейс должен объявить, что throws Exception устраняет ошибку компилятора. Причина этого в том, что вы не передаете тип класса, вы передаете интерфейс Observer. Итак, если один класс, реализующий Observable, выдает исключение, вызывающий класс не узнает об этом, если интерфейс не укажет это.

person Michael K    schedule 09.12.2010

В вашем Observer интерфейсе ваш update() метод не throw Exception, а ваш ConsoleDrawer.update() -. Согласно java, эти два не совпадают.

Либо вы удалите throw Exception на ConsoleDrawer, либо добавите исключение в Observer интерфейс.

person Buhake Sindi    schedule 09.12.2010

В общем, Java позволяет ослабить возвращаемое значение при переопределении метода или усилить параметры. Однако в этом случае вы пытаетесь ослабить параметр.

Может быть, дженерики могут помочь. Должен признать, что я не пробовал приведенный ниже код, это просто по памяти:

Вы можете попробовать использовать дженерики в подписи интерфейса Observer:

public interface Observer<T>

or

public interface Observer<T extends ComponentUpdateEvent>

В дополнение к этому, я бы изменил подпись интерфейса Observable.

public void addObserver(Observer<T extends ComponentUpdateEvent> observer)
person Yoni    schedule 09.12.2010
comment
Либо ваши определения усиления и ослабления инвертированы, чем мои, либо вы перевернули первое предложение. Тип возвращаемого значения переопределенного метода может быть более конкретным (что я бы назвал более сильным), а параметры могут быть менее конкретными (более слабыми). Типы, которые он генерирует, ведут себя аналогично возвращаемым типам. - person Laurence Gonsalves; 09.12.2010