Reputation: 4654
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
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
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