Generic Observer - Casting problems..

I'm trying to make a generic observer pattern, modeled after Wadler's book.

But I get type errors at the lines marked with ? below, and although I fixed them, don't understand why the original code is wrong - any help please!

interface Observer<Sextends Observable><S,O,A>,

Oextends Observer <S,O,A>,

A >{

//?

publicvoid update ( S subject, A arg);

// public void update ( Observable<S,O,A> subject, A arg);

}

abstractclass Observable<Sextends Observable><S,O,A>,

Oextends Observer <S,O,A>,

A >{

List<Observer><S,O,A>> obs =new ArrayList<Observer><S,O,A>>();

boolean changed =false;

// ...

publicvoidnotifyObservers(A a){

// for ( O o : obs ) // ?

//o.update(this,a);// ?

for ( Observer<S,O,A> o : obs )

o.update((S)this,a );// Cast?

};

}

[1808 byte] By [guthriea] at [2007-11-26 20:02:15]
# 1

I haven't read the book. And am I interpreting your posting conventions correctly? Actual code in grey, commented code what you tried to make the compiler happy?

If so then it looks to me like you need a method that gets an S from an Observable<S, O, A>. This is unlikely to be a cast.

DrClapa at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...
# 2

I had no problems with compilation of the following:public interface Observer<S extends Observable><S, O, A>, O extends Observer<S, O, A>, A> {

public void update(Observable<S, O, A> subject, A arg);

}

public abstract class Observable<S extends Observable><S, O, A>, O extends Observer<S, O, A>, A> {

List<Observer><S, O, A>> obs = new ArrayList<Observer><S, O, A>>();

boolean changed = false;

public void notifyObservers(A a) {

for (Observer<S, O, A> o : obs)

o.update(this, a);

};

}

No need for a cast.

stefan.schulza at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...
# 3

Yes, working code in gray, desried (original code) in comments.

There are two questions in the code; the first is at the update call;

Where I wanted to write:

public void update ( Observable<S,O,A> subject, A arg)

but it failed, and I had to change to:

public void update ( S subject, A arg);

It seemed to me that since S was declared in parameter list as:

S extends Observable<S,O,A>

That I knew that by Liskov it was always a subset of the more generic type.

I suppose using S internally is better anyway, so the newer form is OK, I just didn't understand the error it caused.

-

The second case I'll re-think before commenting further!

guthriea at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...
# 4

There were two problems, the first with the declaration of update;

If I changed it from :

public void update ( S subject, A arg);

to:

public void update ( Observable<S,O,A> subject, A arg);

Then the client (below) gave an error:

The type RateView must implement the inherited abstract method Observer<CModel,CView,Currency>.update(Observable<CModel,CView,Currency>, Currency)

I guess that using the S type parameter is better in the update declaration, but I didn't understand the error.

interface CView extends Observer<CModel,CView,Currency> {}

class RateView extends JTextField implements CView {

...

public void update(CModel model, Currency currency) {

...

}

}

class CModel extends Observable<CModel,CView,Currency> {

...

}

The second is on the loop,

And yes, the cast was a mistake; sorry.

My original problem was looping over type O, but using a collection<Observer><...>

Using a Collection<O>,

then the loop for O o : obs) o.update(this,a);

gives error:

The method update(S, A) in the type Observer<S,O,A> is not applicable for the arguments (Observable<S,O,A>, A)

Seems to me it should work..!

So, chasing these errors makes a loop; your code will compile with Observer, but not the client, and mine does get both to work, but seems odd.

Thanks.

guthriea at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...
# 5

Stephan,

I can see that your code works, but don't understand why one would /should have to use the upper bound type limit instead of the actual concrete type in the generics parameter list.

I.e. why in the body one would have to repeat Observer<S, O, A> instead of just using O, since "O extends Observer<S, O, A>".

For example, I would think this should work; but it only does with a (S) cast in the update call argument "this". I understand the error message seems to say that S is more concrete than observable<S,O,A>, but this usage seems odd to me - am I missing something?

interface Observer<S extends Observable><S,O,A>,

O extends Observer <S,O,A>,

A > {

public void update ( S subject, A arg);

}

abstract class Observable<S extends Observable><S,O,A>,

O extends Observer <S,O,A>,

A > {

List<O> obs = new ArrayList<O>();

boolean changed = false;

// ...

public voidnotifyObservers(A a){

for ( O o : obs )

o.update(this,a);// error !

};

}

guthriea at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...
# 6

Stephan,

To illustrate the problem with your version and a client;

The type TestObsGen must implement the inherited abstract method Observer<Thing,TestObsGen,Integer>.update(Observable<Thing,TestObsGen,Integer>, Integer)

Any insights welcome!

public interface Observer<

S extends Observable<S, O, A>,

O extends Observer<S, O, A>,

A> {

public void update(Observable<S, O, A> subject, A arg);

}

abstract class Observable<

S extends Observable<S, O, A>,

O extends Observer<S, O, A>,

A> {

List<Observer><S, O, A>> obs = new ArrayList<Observer><S, O, A>>();

boolean changed = false;

public void notifyObservers(A a) {

for (Observer<S, O, A> o : obs)

o.update(this, a);

};

}

--

public class TestObsGen

implements Observer< Thing, TestObsGen, Integer >

{

Thing thing;

TestObsGen ( Thing t ) {

thing = t;

// t.addObserver(this);

}

void update(Thing t, Integer count) {

System.out.println("Count:" + count);

}

public static void main(String[] args) {

Thing t = new Thing();

TestObsGen test = new TestObsGen(t);

t.bump();

// Event received?!

}

}

class Thing

extends Observable< Thing, TestObsGen, Integer >

{

int count;

void bump() {

count++;

// setChanged();

// notifyObservers();

}

}

guthriea at 2007-7-9 23:01:19 > top of Java-index,Core,Core APIs...