Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Possibly recursive Java generics between two classes

Tags:

java

generics

I'm attempting to produce some classes to control a model-view-presenter application. I've come up with the following definitions, but am struggling to avoid recursive generics.

public abstract class Presenter<V extends View<...?>> {

  protected V view;

  public Presenter(V view) {
    this.view = view;
  }

  // ...
}


public abstract class View<P extends Presenter<...?>> {

  protected P presenter;

  // ...
}

I wanted to enforce a mutual relationship between the two classes. The idea being that I could instantiate a Presenter for a particular View, with both classes relying on useful methods defined in the abstract base classes, yet both knowing exactly what subclass of the counterpart abstract class is in use.

My issues is the defining the ..? part of the code. I can't see a way to avoid a recursive situation, such as:

public abstract class View<P extends Presenter<V>, V extends View<Q>, Q extends...>

and even that definition is not consistent, as the View class now takes two generic parameters... mass confusion.

I basically wanted to avoid the classes being littered with references to the abstract class type, necessitating lots of casting throughout the concrete implementations, as below:

// simpler option

public abstract class Presenter {

  protected View view;    

  public Presenter(View view) {
    this.view = view;
  }
}

public class FooPresenter extends Presenter {

  public FooPresenter(BarView view) {
    super(view);
  }

  public someMethod() {
    ((BarView) getView()).viewSpecificMethod();
  }
}

Each concrete implementation of these classes would need to constantly cast from the abstract type to the type it "knows" is in use.

like image 787
Duncan Jones Avatar asked Oct 12 '22 02:10

Duncan Jones


1 Answers

Use a second type parameter for the type of this:

class Presenter<P extends Presenter<P,V>, V extends View<P,V>> {
    V view;
}

class View<P extends Presenter<P,V>, V extends View<P,V>> {
    P presenter;
}

class MyPresenter extends Presenter<MyPresenter, MyView>{}

class MyView extends View<MyPresenter, MyView>{}

Then you can do:

MyPresenter mp = new MyPresenter().view.presenter;
like image 198
meriton Avatar answered Oct 14 '22 03:10

meriton