2010-09-13 2 views
3

У меня есть абстрактный класс AbstractEvent и некоторые «реальные» классы, расширяющие его. Я хочу сделать абстрактный класс AbstractListener способом process(??? event), чтобы нечерные классы, простирающиеся на AbstractListener, должны были иметь хотя бы один метод, принимающий класс, продолжающийся AbstractEvent. Это возможно?Общее наследование в Java

ответ

16

Вы уже получили название механизма, который вы хотите - generics!

Во-первых, сделать свой класс событий:

abstract class AbstractEvent { 
    // Insert fields/methods common for all events here 
} 

Ничего странного в этом. Затем создайте параметризированный класс слушателя/интерфейс, и дает его параметр типа верхняя граница вашего события класса объектов:

interface Listener<T extends AbstractEvent> { 
    void process(T event); 
} 

Теперь вы можете пойти на создание ваших конкретных классов событий:

class PonyEvent extends AbstractEvent { 
    // Pony-specific stuff goes here 
} 

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

class LoggingPonyListener implements Listener<PonyEvent> { 
    @Override 
    public void process(PonyEvent event){ 
     System.out.println("Pony event occurred: " + event); 
    } 
} 

Теперь, вы можете захотеть, чтобы написать общее событие диспетчерской класс вроде этого:

class EventDispatcher<T extends AbstractEvent> { 
    private final List<Listener<T>> listeners = 
     new CopyOnWriteArrayList<Listener<T>>(); 
    public void addListener(Listener<T> listener) { 
     listeners.add(listener); 
    } 
    public void dispatchEvent(T event) { 
     for (Listener<T> listener : listeners) 
      listener.process(event); 
    } 

} 

выглядит довольно мило, да? Вы можете делать такие вещи, как это:

EventDispatcher<PonyEvent> dispatcher = new EventDispatcher<PonyEvent>(); 
dispatcher.add(new LoggingPonyListener()); 
dispatcher.dispatchEvent(new PonyEvent()); 

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

Не действительно учитывая ваш удивительный EventDispatcher служебный класс, она была написана таким образом:

class DebugListener implements Listener<AbstractEvent> { 
    private final String msg; 
    public DebugListener(String msg) { this.msg = msg; } 
    @Override 
    public void process(AbstractEvent event){ 
     System.out.println(msg); 
    } 
} 

Это должно быть многоразовым, не так ли? Нет, это не будет работать:

EventDispatcher<PonyEvent> dispatcher = new EventDispatcher<PonyEvent>(); 
dispatcher.add(new DebugListener("pony event")); 

Поскольку DebugListener является Listener<AbstractEvent>, не Listener<PonyEvent>.Способ решения этой проблемы было бы использовать нижнюю границу для параметра типа:

class EventDispatcher<T extends AbstractEvent> { 
    private final List<Listener<? super T>> listeners = 
     new CopyOnWriteArrayList<Listener<? super T>>(); 
    public void addListener(Listener<? super T> listener) { 
     listeners.add(listener); 
    } 
    public void dispatchEvent(T event) { 
     for (Listener<? super T> listener : listeners) 
      listener.process(event); 
    } 

} 

Это дает вам поведение вы после: Так же, как вы можете отправить PonyEvent к process методом Listener<AbstractEvent> (т.к. a PonyEvent is-a AbstractEvent), теперь вы можете использовать класс диспетчера событий, параметризованный с типом, для пожарных прослушивателей, параметризованных одним из его супертипов.

0
public abstract class AbstractListener { 
    public abstract void process(AbstractEvent event...); 
} 

Попробуйте это. Это создает абстрактный класс под названием AbstractListener, который имеет один абстрактный метод, который принимает один или несколько абстрактных событий. Если вы абсолютно всегда должны иметь одно событие, вы могли бы попробовать что-то вроде этого (хотя я не могу вспомнить, если это технически возможно):

public abstract class AbstractListener { 
    public abstract void process(AbstractEvent event1, AbstractEvent otherEvents...); 
} 

Надежда, что помогает.

Смежные вопросы