Как заставить "циклические" дженерики работать в Java? - PullRequest
3 голосов
/ 25 августа 2011

У меня ошибка при компиляции следующего кода, включающего несколько обобщений:

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 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>)

На самом деле я хотел бы получить что-то вроде: class A implements HasAState и class B extends State<A>, где B имеет ссылку на A и может вызывать A.addState(B) (только потому, что B расширяет State<A>) и где A можно позвонить B.setParent(this).

Как мне объявить свои занятия так, чтобы то, что я намерен делать, работало?

Спасибо

Ответы [ 2 ]

6 голосов
/ 25 августа 2011

Я согласен с комментарием Эрана Циммермана.Это говорит о том, что вам нужно переосмыслить то, что вы хотите.

В любом случае, я надеюсь, что правильно понял проблему, поэтому я изменил параметр с одного на буксирный, чтобы описать state и hasAState отдельно.

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);
}

Этот код компилируется!- знать о предупреждении для второй строки в setParent.

0 голосов
/ 25 августа 2011

Мой анализ -

  1. A имеет некоторое состояние.(beacuse A implements HasState)

  2. B имеет некоторое состояние через A (содержит ссылку A) (потому что B extends State<A>)

  3. Состояние в A выше по существу сохраняется в B (из-за A.addState(B)) (?)

    Это очень запутанный дизайн, как мне кажется.Можете ли вы опубликовать, в чем суть вашего дизайна, не упоминая о них методы и параметры?

...