2009-07-09 4 views
4

Ich habe eine generische Observer-Schnittstelle und eine Observable-Klasse gemacht, aber kann meine Klasse wegen einiger Generika Problem nicht kompilieren. Ich weiß nicht genau, warum das, was ich versuche, verboten ist. Der Code folgt:Problem mit Beobachter Muster und Generika in 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

Können Sie die spezifische (n) Fehlermeldung (en) angeben, die Sie erhalten? –

+0

Nach Korrektur der Listendeklaration: Von Eclipse: Die Methode atualizar (Capture # 4-of? Erweitert Observable , U) im Typ Observer , U> ist nicht anwendbar für die Argumente (Observable , U) –

+0

Ersetzen Sie "atualizar" für "update" in meinem letzten Kommentar. –

Antwort

3

Try this:

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

das zugrunde liegende Problem erklären hier, Generika sind Forci einen expliziten Downcast. Sie können also keine Observable für irgendeine Implementierung von U verwenden und sie in eine Sammlung einfügen, da diese Sammlung definiert ist als eine bestimmte Art von U zu nehmen, nichts.

Für diese Art von Anwendungsfall haben Generika Grenzen, und Sie sind möglicherweise nicht in der Lage, das zu erreichen, was Sie auf eine solche Art sicher erreichen möchten.

EDIT: Würde das für Sie arbeiten?

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

Dies löst das Problem bei der Methode notifyObservers(), aber das Problem ate Methode addObserver() bleibt bestehen. –

+0

Fehlermeldung: Die Methode hinzufügen (Beobachter , U>) in der Art Liste , U >> ist nicht anwendbar für die Argumente (Observer , U>) –

+0

In was ich gepostet habe gibt es keine mehr. Hast du auch die andere Methodensignatur geändert? – Yishai

6

Ihre _observers Definition Um dies ändern:

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

Wenn Sie sublclasses Sie diese müssen zulassen möchten in der Erklärung geben, nicht nur in dem Sie es verwenden

+0

Jetzt, wo ich den Code anschaue, ist das wahrscheinlich das Problem. –

+0

Das löst das Problem, aber gibt es einen Grund, dass ich das auch in der Deklaration angeben sollte? Diese Korrektur verursachte ein anderes Problem in anderem Teil des Codes. Ich werde die Frage bearbeiten und alles posten. –