alfoks
alfoks

Reputation: 4654

Implementing generic type interface

Let's say I have the following interfaces:

public interface MvpView { }

public interface MvpPresenter<V extends MvpView> {
    void attach(V view);
}

Then a base class that implements MvpPresenter

public class BasePresenter<V extends MvpView> implements MvpPresenter<V> {
    private V view;

    @Override
    public void attach(V view) {
        this.view = view;
    }
}

And finally the following class that extends BasePresenter

public abstract class BaseFragment<P extends MvpPresenter> implements MvpView {
    P presenter;

    public void someMethod() {
        presenter.attach(this);
    }
}

While this compiles it's not safe because there is no guarantee that implementations of the class will implement the correct MvpView (the one that P presenter uses). In order to be safe I've left out the code of someMethod and every implementation must fill it with the exact same code presenter.attach(this)

What I'd like to do but I don't know how is something like the following:

public abstract class BaseFragment<V extends MvpView, P extends MvpPresenter<V>> implements V {
    P presenter;

    public void someMethod() {
        presenter.attach(this);
    }
}

Is there any way to achieve this?

Upvotes: 1

Views: 169

Answers (2)

alfoks
alfoks

Reputation: 4654

Based on boobalan gnanasekaran and user158037 answers, I did it like this:

public interface MvpView { }

public interface MvpPresenter<V extends MvpView> {
    void attach(V view);
}

public class BasePresenter<V extends MvpView> implements MvpPresenter<V> {
    private V view;

    @Override
    public void attach(V view) {
        this.view = view;
    }

    public V getView() {
        return view;
    }
}

public abstract class BaseFragment<V extends MvpView, P extends MvpPresenter<V>> {
    P presenter;

    protected abstract V getThis();

    public void someMethod() {
        presenter.attach(getThis());
    }

    public P getPresenter() { return presenter; }
}

And an example implementation

public interface MoviesContract {
    interface Presenter extends MvpPresenter<MoviesContract.View> {
        void loadMovies();
    }

    interface View extends MvpView {
        void onMoviesLoaded();
    }
}

public class MoviesPresenter extends BasePresenter<MoviesContract.View>
    implements MoviesContract.Presenter {

    @Override
    public void loadMovies() {
        getView.onMoviesLoaded();
    }
}


public class MoviesFragment extends BaseFragment<MoviesContract.View, MoviesContract.Presenter>
    implements MoviesContract.View {

    @Override
    public MoviesContract.View getThis() {
        return this;
    }

    public loadMovies() {
        getPresenter().loadMovies();
    }

    @Override
    public void onMoviesLoaded() {
        //
    }
}

Upvotes: 0

Alanpatchi
Alanpatchi

Reputation: 1199

Declare BaseFragment like this.

abstract class BaseFragment<P extends MvpPresenter<R>, R extends BaseFragment<P,R>> implements MvpView {
    P presenter;

   public void someMethod() {
        presenter.attach(getThis());
   }

   abstract R getThis();
   }
}

and use the extensions like this,

class MyFragment extends BaseFragment<MvpPresenter<MyFragment>, MyFragment> {

    @Override
    MyFragment getThis() {
        return this;
    }   

}

Upvotes: 3

Related Questions