2010-09-13 225 views
3

我有一個抽象類AbstractEvent和一些擴展它的「真實」類。我想用一個方法process(??? event)創建一個抽象類AbstractListener,以便擴展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")); 

因爲DebugListenerListener<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); 
    } 

} 

這給你你後的行爲:就像你可以發送PonyEventListener<AbstractEvent>process方法(因爲一個PonyEvent is-an 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...); 
} 

希望有所幫助。