samedi 21 février 2015

Type safe observer pattern with generics compile time error

Requirements


I am trying to write an Observer, Observable pair of classes. I want to parametrize the Observer so that a type safe update call is possible. Imagine this version:



class View implements Observer<Model> {
@Override
public void update(Model model) { render(model); } // no casting:)
}


instead of this version that needs casting:



class View implements Observer {
@Override
public void update(Object model) { render((Model) model); } // casting:(
}


Attempt


Here's what I have so far. My Observer interface:



public interface Observer<T extends Observable> {
public void update(T observable);
}


and my Observable abstract class:



import java.util.List;

public abstract class Observable {
private List<Observer<? extends Observable>> observers;

public Observable() {
System.out.println(this.getClass());
}

public void addObserver(Observer<? extends Observable> obs) {
observers.add(obs);
}

public void removeObserver(Observer<? extends Observable> obs) {
observers.remove(obs);
}

protected <E extends Observable> void updateObservers(E self) {
for (Observer<? extends Observable> obs : observers) {
obs.update(self); // <-------------------- COMPILER ERROR!!!
}
}
}


Problem


The line labeled "COMPILER ERROR" has a problem with the .update():



The method update(capture#4-of ? extends Observable) in the type Observer is not applicable for the arguments (E)



So even though the self argument passed to update() is of type E extends Observable, it does not satisfy the interface method signature update(T observable); where T extends Observable. Why is that? I really expected those to be compatible.


Is there I can fix this to meet my requirements?


Thanks.


Aucun commentaire:

Enregistrer un commentaire