【问题标题】:Generic inheritance in JavaJava中的泛型继承
【发布时间】:2011-04-11 20:20:06
【问题描述】:

我有一个抽象类AbstractEvent 和一些扩展它的“真实”类。我想用process(??? event) 方法创建一个抽象类AbstractListener,以便扩展AbstractListener 的非抽象类需要至少有一个方法接受扩展AbstractEvent 的类。这可能吗?

【问题讨论】:

    标签: java oop generics inheritance


    【解决方案1】:

    你已经得到了你想要的机制的名称 - 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&lt;AbstractEvent&gt;,而不是Listener&lt;PonyEvent&gt;。解决这个问题的方法是使用参数类型的下限:

    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 发送到Listener&lt;AbstractEvent&gt;process 方法(因为PonyEventAbstractEvent),您现在可以使用使用类型参数化的事件调度程序类来触发使用其超类型之一参数化的侦听器。

    【讨论】:

      【解决方案2】:
      public abstract class AbstractListener {
          public abstract void process(AbstractEvent event...);
      }
      

      试试看。这将创建一个名为 AbstractListener 的抽象类,该类具有一个接受一个或多个抽象事件的抽象方法。如果您绝对必须始终举办一个活动,您可以尝试这样的事情(尽管我不记得这在技术上是否可行):

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

      希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-25
        • 1970-01-01
        • 2011-03-06
        • 1970-01-01
        • 2021-10-11
        • 1970-01-01
        相关资源
        最近更新 更多