samedi 3 janvier 2015

Is using generics to indicate some class/method is aware of a type good idea?


I'm going to use Java for code/idea demonstration.


Imagine it's needed to define two interfaces: Observer and Observable (observer pattern). It's a good idea to have two generic interfaces, so there is no restriction on what is being observed, who is observing it (is even using generics about this?).


Java has a concrete (non-final) Observable class and an Observer interface. You have to delegate handling observers and notifying them on update to the concrete Observer class. This is one way of implementing the pattern. I don't know if it's the best approach (probably is), but for the sake of this example let's assume every class/type who wants to be observable, must implement the Observable interface below, and handle everything itself.


We should not forget the original Observer and Observable interface/object were implemented in JDK1.0, when generics were not available.


Now the question: Is this a good idea to merely declare a generic type in an interface to denote that the implementing class needs to be aware of some specific type? Or it is totally wrong way of using generics?


See:



public interface Observable<T> {
// Only observers who are aware of type T are allowed.
// But should really Observable be concerned about it?
public void registerObserver(Observer<? extends T> o);
}

// The T here denotes that implementing class will be aware of a type called T,
// (not that it can operate on a range of types).
public interface Observer<T> {
// Observer is not aware of Observable interface directly. But it knows about T.
public void update(T arg);
}


VS



public interface Observable {
// Is it an observer? then it is allowed. That's all we need to know.
public void registerObserver(Observer o);

// Observers will be passed the instance of observable,
// then they call this method to fetch arg.
// something like:
// for(Observer o: this.observers) o.update(this);
public <T> T getArg();
}

public interface Observer {
// Pass me an Observable who returns T and i'll do the rest!
public void update(Observable o);
}


I feel I'm getting generics totally wrong.


P.S: Comparing this way of implementing the observer pattern (asking every type to re-implement these interfaces) vs the original java solution (delegation) we realize it's not really a good idea. It causes a lot of code duplicate. But it helps to understand generics better.





Aucun commentaire:

Enregistrer un commentaire