代码之家  ›  专栏  ›  技术社区  ›  Thiago Chaves

Java中的观测器模式和泛型问题

  •  4
  • Thiago Chaves  · 技术社区  · 15 年前

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

    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 回复  |  直到 15 年前
        1
  •  3
  •   Yishai    15 年前

    试试这个:

     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的实现获取任何“可观察的”并将其放入集合中,因为该集合被定义为获取特定类型的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);
       }
    
        2
  •  6
  •   tddmonkey    15 年前

    将观察者定义更改为:

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

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