2009-07-09 9 views
4

J'ai créé une interface Observer générique et une classe Observable, mais je ne peux pas compiler ma classe en raison de problèmes génériques. Je ne sais pas précisément pourquoi ce que j'essaie de faire est interdit. Le code suivant:Problème avec le modèle Observateur et les génériques en Java

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

Pouvez-vous fournir le (s) message (s) d'erreur spécifique (s) que vous obtenez? –

+0

Après avoir corrigé la déclaration de la liste: A partir de Eclipse: La méthode atualizar (capture # 4-of? Extends Observable , U) dans le type Observateur , U> ne s'applique pas aux arguments (Observable , U) –

+0

Remplacer "atualizar" par "update" dans mon commentaire précédent. –

Répondre

3

Essayez ceci:

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

expliquer ici le problème sous-jacent, les médicaments génériques sont Forci un downcast explicite. Donc, vous ne pouvez pas prendre 'Observable' pour n'importe quelle implémentation de U et le mettre dans une collection, parce que cette collection est définie comme prenant un type spécifique de U, pas n'importe quoi.

Pour ce type de cas d'utilisation, les génériques ont des limites, et il se peut que vous ne puissiez pas accomplir ce que vous voulez de manière sécurisée.

EDIT: Cela fonctionnerait-il pour vous?

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

Cela résout le problème à la méthode notifyObservers(), mais le problème ate méthode addObserver() reste. –

+0

Message d'erreur: La méthode ajouter (Observateur , U>) dans le type Liste , U >> ne s'applique pas aux arguments (Observateur , U> –

+0

Dans ce que j'ai posté il n'y a plus d'extensions. Avez-vous également modifié la signature de l'autre méthode? – Yishai

6

Changer votre définition de _observers à ceci:

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

Si vous souhaitez autoriser les sous-classes, vous devez préciser dans la déclaration, non seulement à l'endroit que vous l'utilisez

+0

Maintenant que je regarde le code, c'est probablement le problème. –

+0

Cela résout le problème, mais y a-t-il une raison que je devrais spécifier cela dans la déclaration aussi? Cette correction a causé un autre problème dans l'autre partie du code. Je vais éditer la question et poster tout. –