I know there are many (!) Q/A on this general topic; but haven't yet been able to resolve my specific approach.
I adapted this code from a Scala example by Odersky, which shows mutually recursive generic types to show a bi-directional link ability between Observer & Observed.
In Subject::publish() when I broadcast the event to all observers, even though my type is Subject<S,O>, and the target Observer is of type <S,O> and thus also its notify method; I get a type error,
The method notify(S) in the type Observer<S,O> is not applicable for the arguments (Subject<S,O>)
unless I explicitly cast the passed argument to notify().
obs.notify( (S) this ); The types seem right, but the compiler disagrees(!).
May be something silly, but it eludes me. TIA
abstract class Subject< S extends Subject< S, O >,
O extends Observer< S, O > > {
private final List< O > observers = new ArrayList<O>();
void subscribe( O obs ) { observers.add( obs ); }
void publish() {
for ( final O obs : observers )
// TThe method notify(S) in the type Observer<S,O> is not applicable for the arguments (Subject<S,O>)
obs.notify( this ); // (S)this ??
}
}
//-------------------------------------------------------------
abstract class Observer< S extends Subject< S, O >,
O extends Observer< S, O > > {
abstract void notify( S sub );
}
//-------------------------------------------------------------
class Sensor extends Subject< Sensor, Display > {
double value = 0.0;
String name = "";
Sensor(String nm) { name = nm; }
void changeValue( final double v ) {
value = v;
publish();
}
public String toString() { return "Sensor:" + name; }
}
class Display extends Observer< Sensor, Display > {
void notify( Sensor sub ) { // Note typed argument!
System.out.println( sub + " has value " + sub.value );
}
}
//-------------------------------------------------------------
public class SubjectObserver {
public static void main( final String[] notUsed ) {
final Display o = new Display();
final Sensor s = new Sensor("Temperature");
s.subscribe( o );
s.changeValue( 1 );
}
}