3

I am having an error while compiling the following code involving a few generics:

public abstract class State<T extends HasAState<? extends State<T>>>{
    protected T parent;

    public void setParent(){ // It's been simplified for the sake of the question!
        parent.removeState(this); // Error here!
        this.parent = parent;
        parent.addState(this);    // Error here!
    }
}

public interface HasAState<T extends State<? extends HasAState<T>>> {
    public void addState(T state);
    public void removeState(T state);
}

The errors are: The method removeState(capture#1-of ? extends State<T>) in the type HasAState<capture#1-of ? extends State<T>> is not applicable for the arguments (State<T>)

Actually what I would like to have is something like: class A implements HasAState and class B extends State<A> where B has a reference to A and can call A.addState(B) (only because B extends State<A>) and where A can call B.setParent(this).

How should I declare my classes so that what I intend to do work?

Thanks

wattostudios
  • 8,666
  • 13
  • 43
  • 57
Jean Logeart
  • 52,687
  • 11
  • 83
  • 118
  • 4
    I think you should re-think your design... Are all these generics really necessary? Maybe there's a much more simple way to do what you're trying to achieve? – Eran Zimmerman Gonen Aug 25 '11 at 07:51
  • 1
    [Here](http://stackoverflow.com/questions/2567595/creating-circular-generic-references/2656027#2656027) is one way to create circular generic references in Java. If this is not what you are looking for, [browse similar threads](http://stackoverflow.com/search?q=[java]+[generics]+circular&submit=search). – Péter Török Aug 25 '11 at 07:53
  • I tried your suggestion but I get another error at the same location: `The method addState(E) in the type HasAState

    is not applicable for the arguments (State

    )`

    – Jean Logeart Aug 25 '11 at 08:05

2 Answers2

5

I agree with the comment of Eran Zimmerman. It seams that you need to rethink about what you want.

Anyway I hope I have understand the problem right, so I changed the Parameter from one to tow, to describe the state and the hasAState separately.

public abstract class State<S extends State<S, H>, H extends HasAState<S, H>>{
    protected H parent;

    public void setParent(){ 
        parent.removeState(this);
        this.parent = parent; //!!!this line has no effect!!!
        parent.addState(this);        
    }       
}

public interface HasAState<S extends State<S, H>, H extends HasAState<S, H>> {
    public void addState(State<S, H> state);
    public void removeState(State<S, H> state);
}

This code compiles! -- be aware of the warning for the second line in setParent.

Ralph
  • 118,862
  • 56
  • 287
  • 383
0

My Analysis -

  1. A has some state. ( beacuse A implements HasState )

  2. B has some state through A ( by containing a reference of A ) ( because B extends State<A>)

  3. The state in A above is essentially held in B ( because of A.addState(B) ) ( ? )

    This is a very convoluted design as it appears to me. Can you post what is your design essence without mentioning methods and parameters to them ?

Community
  • 1
  • 1
Bhaskar
  • 7,443
  • 5
  • 39
  • 51