【问题标题】:How do I make a Class extend Observable when it has extended another class too?当一个类也扩展了另一个类时,如何使一个类扩展 Observable?
【发布时间】:2009-11-01 23:04:20
【问题描述】:

我正在学习 Java,我想将我的课程变成一个可观察的课程。

但是我已经让它扩展了另一个类。

我该怎么办?

【问题讨论】:

    标签: java


    【解决方案1】:

    我建议完全避免使用Observable 类,而是定义特定于事件的侦听器和相应的事件定义。然后在您的类中定义一个侦听器列表以及添加和删除侦听器的方法,并将事件传播给它们(见下文)。

    Observable 强制您使用java.lang.Object 表示事件,然后使用instanceof 检查事件类型,这是一种丑陋的非OO 方法,并且使代码更难理解。如果您查看 javax.swing 包中的类,您会发现它们完全避免使用 Observer / Observable 并使用类似于以下的方法。

    事件定义

    public class MyChangeEvent extends EventObject {
      // This event definition is stateless but you could always
      // add other information here.
      public MyChangeEvent(Object source) {
        super(source);
      }
    }
    

    监听器定义

    public interface MyChangeListener {
      public void changeEventReceived(MyChangeEvent evt);
    }
    

    类定义

    public class MyClass {
      // Use CopyOnWriteArrayList to avoid ConcurrentModificationExceptions if a
      // listener attempts to remove itself during event notification.
      private final CopyOnWriteArrayList<MyChangeListener> listeners;
    
      public class MyClass() {
        this.listeners = new CopyOnWriteArrayList<MyChangeListener>();
      }
    
      public void addMyChangeListener(MyChangeListener l) {
        this.listeners.add(l);
      }
    
      public void removeMyChangeListener(MyChangeListener l) {
        this.listeners.remove(l);
      }
    
      // Event firing method.  Called internally by other class methods.
      protected void fireChangeEvent() {
        MyChangeEvent evt = new MyChangeEvent(this);
    
        for (MyChangeListener l : listeners) {
          l.changeEventReceived(evt);
        }
      }
    }
    

    【讨论】:

    • java.util.Observable 还有一个标志来指示是否有任何改变。有时一个新的 Event 类是矫枉过正的。
    • @finnw - 我的大多数事件类定义都是
    • CopyOnWriteArrayList 是必需的,除非您想要同步 fireChangeEvent、addMyChangeListener 和 removeMyChangeListener 方法,或者如果您在 for 循环运行时添加/删除,则获取 java.util.ConcurrentModificationException。如果列表不经常添加/删除(并且在大多数情况下可能不是),则 COpyOnWriteArrayList 可能会更好。
    • +1 表示 CopyOnWriteArrayList。没有它,正确地获得可重入语义是一件痛苦的事情,而且它比总是复制更有效。
    • @TofuBeer:在所有方法上同步将不起作用:如果调用 fireChangeEvent() 并通知侦听器并尝试删除自身,这仍然会导致 ConcurrentModificationException,因为执行通知的线程已经持有对象锁,因此可以不阻塞地调用removeChangeListener
    【解决方案2】:

    Java 不允许多重继承,因此没有直接的方法可以做到这一点。您应该考虑使用委托模式,让您的主要对象将他的观察者行为委托给另一个对象..

    class YourObject extends ItsAncestorClass
    {
          private Observer includedObserver;
    
          public Observer getHisObserver(..)
    }
    

    另一种方法是将您的类从中扩展的对象转换为接口,然后您将被允许从 Observer 扩展。

    【讨论】:

    • @finnw - Jack 从来没有说过 Observer 不是一个抽象类。
    【解决方案3】:

    另一种选择是将对象包装在 Observable 对象中。

    public class MyObjectObservableWrapper implements Observable {  
      private MyObject myObject;
      public MyObjectObservaleWrapper(MyObject myObject){
        this.myObject = myObject;
      }
      // interface methods here
    }
    

    当 Observable 方法使用的数据可以通过 MyObject 的公共方法访问时,此选项有效。因此,它可能并不适合所有情况。

    【讨论】:

      【解决方案4】:

      多重继承(扩展两个类)在 Java 中是不可能的。几乎在所有情况下都被认为是糟糕的设计。

      如果您提供更多信息,也许有人可以为您提供更多帮助。

      【讨论】:

        【解决方案5】:

        您可以扩展 Observable 并将原始父级包装在您的可观察子类中。将所有方法调用委托给被包装的对象。

        【讨论】:

          【解决方案6】:

          使用桥梁。

          创建一个扩展 Observable 的类,第一个类只调用第二个类的方法。

          桥接方法详解:

           public class XXX {
              public class XXXObservableBridge : Observable {
                 public void RaiseEvent();
                 // Listeners etc
              }
          
              private XXXObservableBridge ObservableBridge;
          
              XXX() {
                 ObservableBridge = new ObservableBridge;
              }
          
              public Observable AsObservable() { return ObservableBidge; }
          
              public void RaiseEvent() { ObservableBridge.RaiseEvent(); }
           }
          

          【讨论】:

          • -1 这是一个 Java 问题,而不是 C#。请坚持 Java 语法和 API
          • @finnw C# 不需要 observable/observer 模式,我的代码甚至不调用任何 API 函数。
          • Java中没有IObservable,即使你定义了,java.util.Observable也没有实现。
          猜你喜欢
          • 2023-03-14
          • 1970-01-01
          • 2020-10-05
          • 2012-12-07
          • 2013-04-09
          • 1970-01-01
          • 2020-02-06
          • 1970-01-01
          • 2021-11-19
          相关资源
          最近更新 更多