Java中观察者模式和泛型的问题

时间:2009-07-09 13:36:58

标签: java generics observer-pattern

我已经创建了一个通用的Observer接口和一个Observable类,但由于一些泛型问题而无法编译我的类。我不知道为什么我要做的事情是被禁止的。代码如下:

public class Observable<U> {

    private List<Observer<Observable<U>, U>> _observers = 
            new ArrayList<Observer<Observable<U>, U>>();

    public void addObserver(Observer<? extends Observable<U>, U> obs) {
        if (obs == null) {
            throw new IllegalArgumentException();
        }
        if (_observers.contains(obs)) {
           return;
        }
        _observers.add(obs); // This line does not compile
    }

    public void notifyObservers(U data) {
        for (Observer<? extends Observable<U>, U> obs : _observers) {
            // After correction of the list declaration, this line will not compile
            obs.update(this, data); 
        }        
    }
}

interface Observer<T, U> {
    public void update(T entity, U arg);
}

2 个答案:

答案 0 :(得分:6)

将_observers定义更改为:

private List<Observer<? extends Observable<U>, U>> _observers = 
        new ArrayList<Observer<? extends Observable<U>, U>>();

如果您想要允许子类,您需要在声明中指定它,而不仅仅是在您使用它的地方

答案 1 :(得分:3)

试试这个:

 public class Observable<U> {

        private List<Observer<Observable<U>, U>> _observers =
                new ArrayList<Observer<Observable<U>, U>>();

        public void addObserver(Observer<Observable<U>, U> obs) {
            if (obs == null) {
                throw new IllegalArgumentException();
            }
            if (_observers.contains(obs)) {
               return;
            }
            _observers.add(obs);            }

        public void notifyObservers(U data) {
            for (Observer<? super Observable<U>, U> obs : _observers) {
                obs.atualizar(this, data);
            }
        }
    }

    interface Observer<T, U> {
        public void atualizar(T entity, U arg);
    }

为了解释这里的根本问题,泛型正迫使明确的向下倾斜。因此,你不能对U的任何实现采取任何'Observable'并将其放入集合中,因为该集合被定义为采用特定类型的U,而不是任何东西。

对于这种类型的用例,泛型有限制,您可能无法以这种类型安全的方式完成您想要的任务。

编辑:这对你有用吗?

public class Observable<U> {

       private List<Observer<U>> _observers =
               new ArrayList<Observer<U>>();

       public void addObserver(Observer<U> obs) {
           if (obs == null) {
               throw new IllegalArgumentException();
           }
           if (_observers.contains(obs)) {
              return;
           }
           _observers.add(obs);            }

       public void notifyObservers(U data) {
           for (Observer<U> obs : _observers) {
               obs.atualizar(this, data);
           }
       }
   }

   interface Observer<U> {
       public void atualizar(Observable<U> entity, U arg);
   }