Java中的通用继承

Flu*_*ffy 3 java oop generics inheritance

我有一个抽象类AbstractEvent和一些扩展它的"真正"类.我想AbstractListener用一个方法创建一个抽象类,process(??? event)这样AbstractListener就不需要扩展非抽象类,至少有一个方法接受一个类扩展AbstractEvent.那可能吗?

gus*_*afc 16

你已经得到了你想要的机制的名称 - 泛型!

首先,制作你的活动课程:

abstract class AbstractEvent {
    // Insert fields/methods common for all events here
}
Run Code Online (Sandbox Code Playgroud)

没什么好奇的.接下来,创建一个参数化的侦听器类/接口,并为其类型参数赋予事件对象类的上限:

interface Listener<T extends AbstractEvent> {
    void process(T event);
}
Run Code Online (Sandbox Code Playgroud)

您现在可以继续制作特定的活动课程:

class PonyEvent extends AbstractEvent {
    // Pony-specific stuff goes here
}
Run Code Online (Sandbox Code Playgroud)

而且,这应该是你所需要的.继续并实现您的侦听器类:

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

现在,您可能想要编写一个通用的事件调度类,如下所示:

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

}
Run Code Online (Sandbox Code Playgroud)

看起来很甜蜜,嗯?你可以做这样的事情:

EventDispatcher<PonyEvent> dispatcher = new EventDispatcher<PonyEvent>();
dispatcher.add(new LoggingPonyListener());
dispatcher.dispatchEvent(new PonyEvent());
Run Code Online (Sandbox Code Playgroud)

完全甜蜜,我们可以使用这些东西,然后当我们使用它时,继续重复使用它.但是有一个问题.假设你有一个聪明的开发人员想要一个超级简单的监听器,它实际上并没有对事件对象做任何事情,只是在事件发生时打印一个指定的消息.

不是真的考虑你真棒的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该是可重用的,对吧?不,这不起作用:

EventDispatcher<PonyEvent> dispatcher = new EventDispatcher<PonyEvent>();
dispatcher.add(new DebugListener("pony event"));
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)

这给你你后的行为:就像你可以发送PonyEventprocess的方法Listener<AbstractEvent>(因为PonyEvent是-的AbstractEvent),你现在可以使用事件调度类参数,类型为火听众参数与其父类型之一.