Is it possible to have something like that? I'm trying to force any class extending this one to implement an interface that extends BaseHomeListView
public abstract class BaseHomeFragment<T extends BaseHomeListView> extends BaseRecyclerViewFragment implements T
I'm trying to implement MVP pattern in Android for some fragments which only display lists.
So basically the view has to rendersList, that's why it is in the base interface, however I still want to allow each fragment to have add more methods as they need
public interface BaseHomeListView<T> extends LoadDataView, LoadMoreView<T> {
void renderList(Collection<T> items);
}
The only sensible thing you can do is the following:
public abstract class BaseHomeFragment<T>
extends BaseRecyclerViewFragment
implements BaseHomeListView<T>
And then if you have something like
public interface FancyHomeListView extends BaseHomeListView<Fancy> {
}
Then you can just have a fragment like
public class FancyHomeFragment
extends BaseHomeFragment<Fancy>
implements FancyHomeListView {
//...
}
Assuming you want to change the implementation of the interface's methods in every subclass, but not the arguments of such methods, or decouple the business code of the fragment's views, it would be more reasonable to add a generic instance of such interface as a member of your fragment class.
public abstract class BaseHomeFragment<T extends BaseHomeListView> extends BaseRecyclerViewFragment {
/*the class information can be used against a factory method to get an instance of the interface*/
private Class<T> myInterfaceClass;
protected T myInterfaceInstance;
public void setMyInterFaceInstance(T instance){
myInterfaceInstance = instance;
}
public BaseHomeFragment(Class<T> initializeClass){
myInterfaceClass = initializeClass;
myInterfaceInstance = interfaceFactory(myInterfaceClass);
}
//TODO: use the interface instance.
}
now, in every subclass, you'll need to add the interface subclass as an argument to super:
public class myAppHomeFragment extends BaseHomeFragment<AppHomeListView>{
public myAppHomeFragment(){
super(AppHomeListView.class);
setMyInterFaceInstance(new AppHomeListView{
//Method overloading
});
}
//TODO: Use the interface's new methods if necessary.
}
a little example of your factory method:
public static <T extends BaseHomeListView> T interfaceFactory(Class<T> aClass){
if(aClass.getSimpleName().equals("someclass")){
//TODO
return new someclass;
}
return null;
}
Related
I'm pretty new to Java and it's safe to say I'm just taking my first steps. So I'm sorry if the question is a little awkward.
Basically I would like to know what would be the best approach to solving the issue I have.
I've got an abstract class BasePage and HomePage that is supposed to be derived from the former. All pages can be loaded, so it makes sense to define the load method on the BasePage, but I would like the method to return the type of HomePage in this case and SubClass type in general.
From what I've learnt , seems like it's not that easy and I started to think maybe it's because it's a flawed design.
I also have a few methods that are valid for all pages, one of them is confirmAge, cos no matter what page you go to, you're always greeted with the age gate and basically you have to confirm you're above 18 to proceed. So since it's something fundamental, I believe it should be coded into the BasePage.
Anyway, no matter what I use - abstract classes or interfaces, I have the same issue with return type and I would really like to enforce some interface on all the classes derived from BasePage.
Any help would be appreciated.
Simplest way addressing your use-case - relying on covariant return types
Example:
public abstract class BasePage {
public abstract BasePage load();
}
public class HomePage extends BasePage {
#Override
public HomePage load() {
//...
return this;
}
}
If you require also polymorphic arguments in addition to return types - make use of generics
Example:
public abstract class BasePage <T extends BasePage<T>> {
public abstract T load();
public abstract void copyFrom(T another);
}
public class HomePage extends BasePage<HomePage> {
#Override
public HomePage load() {
//...
return this;
}
#Override
public void copyFrom(HomePage another) {
//...
}
}
Note, that second <T> in the generic definition can be omitted, giving a shorter
class BasePage <T extends BasePage>
and in this case, compiler will infer
class BasePage <T extends BasePage<?>>
which is still suitable for your general case
You can add the actual Type as a type parameter for the BasePage:
public abstract class BasePage<T extends BasePage<?>> {
public abstract T load();
}
public class HomePage extends BasePage<HomePage> {
#Override
public HomePage load() {
return new HomePage();
}
}
One solution is to use generics:
public abstract class SuperClass<T extends SuperClass<T>> {
protected abstract T someMethod();
}
public class SubClass extends SuperClass<SubClass> {
protected SubClass someMethod() {
return this;
}
}
Generics is best option here. You can T type interface here. Here is an example:
public interface Service<T> {
T execute();
}
public class MyService implements Service<String> {
private final String input1;
private final int input2;
public MyService(String input1, int input2) {
this.input1 = input1;
this.input2 = input2;
}
#Override
public String execute() {
return String.format("'%s%d'", input1, input2);
}
}
I would design it like this: Create an abstract class BaseClass and leave the loadPage method unimplemented (abstract method). Now, whatever classes extend from BaseClass can have their own implementations of loadPage.
Or, write a basic loadPage method in the base class. This method should contain operation like making a GET request, that should be common to all classes whose objects require loading pages. Then, in the sub-classes of the base class, create some method like: homePageLoader. This method can call pageLoader in the base class to make GET requests.
I was trying to implement a way to decouple View and Presenter in the MVP pattern to provide a framework, which does exactly this, but after a point I got confused.
Background
I have a View interface with a generic type for the connected presenter and vice versa. Those interfaces are to be extended by the implementing developer. The concrete interface is not of interest for this question, but the class definition of those both look like the following:
public interface Presenter<T extends View>
and
public interface View<T extends Presenter>
The idea is that both the View and the Presenter know the opposing interface.
For using this structure, the developer should provide a factory, that instantiates the View he wants to show and the Presenter that is handling this View. He gives both of them to a class called the SuperController. They are associated by the class of the View.
The PresenterFactory interface, which creates the Presenter, has no parameters and returns a Presenter implementation and looks the following:
public interface PresenterFactory<T extends View> {
<S extends Presenter<T>> S create();
}
The ViewFactory interface, which creates the View, creates a View implementation, based on the Presenter and looks the following:
public interface ViewFactory<T extends View, S extends Presenter<T>> {
T create(S presenter);
}
Problem
The problem I am encountering is the following:
I wanted to provide an example with a TestView and a TestPresenter. Those look like this:
public interface TestPresenter extends Presenter<TestView> {...}
public interface TestView extends View<TestPresenter> {...}
Also, a ViewFactory is provided, which looks like this:
class TestViewFactory implements ViewFactory<TestView, TestPresenter> {
#Override
public TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
And this is the TestPresenterFactory:
private class TestPresenterFactory implements PresenterFactory<TestView> {
#Override
public <S extends Presenter<TestView>> S create() {
return new TestPresenterImpl();
}
}
This code cannot be compiled. The problem is the return value of the TestPresenterFactory. Java says, it expects S and not a TestPresenterImpl. Also, casting to TestPresenter will not work. However, casting to S will work. It than can be compiled and also runs successfully, but this is not what I wanted the implementing developer to do.
Why does this problem exist? And why does casting to the concrete interface not work? In my opinion, this should work, because the TestPresenterImpl implements the TestPresenter, which extends Presenter of the generic type TestView yet it is not compilable.
The following does work. If you change the PresenterFactory definition like this:
public interface PresenterFactory<T extends View, S extends Presenter<T>> {
S create();
}
with the example implementation now looking like this:
private class TestPresenterFactory implements PresenterFactory<TestView, TestPresenter> {
#Override
public TestPresenter create() {
return new TestPresenterImpl();
}
}
It can be compiled and run, just like if I cast to S in the above example.
However, this is not what I want. The generic type declaration is redundant. Letting the implementing developer declare the View and the presenter, to only create the Presenter looks awkward. It would be really great if the type could inferred at the method.
Also, I do not want to force the implementing developer to cast to S.
Is there a more elegant way for this?
edit
A question was brought up as a duplicate and I want to distance myself from this question.
The problem that arises from this has nothing to do with Producer Extends Consumer Super. I have two producers (factories) in use. Both of which are producing a class. One depends on another class (the View depends on the Presenter), while the other one is without dependency (the Presenter can be instantiated with a default constructor). All respected interfaces have the T extends XYZ definition, to allow the production of interfaces, which inherit of that interface (either the Presenter or the View).
The real problem here is that the generic within the ViewFactory can be inferred by Java. Both of the generic types are declared within the class definition. Within the PresenterFactory, the method-level generic cannot be inferred by Java. Even though, the generic type is the same as the one in the view factory <S extends Presenter<T>>; at the method, this type cannot be inferred.
The solution is to either cast (which I don't want the using developer to do) or to declare the PresenterType in the class definition (which seems to be redundant. The only thing of interest is, that the view is defined and any Presenter for that view is returned).
My question is what can I do to work around said issues that are a result of the extends clause?
For starters, this will solve the problem:
interface PresenterFactory<T extends View, S extends Presenter<T>> {
S create();
}
class TestPresenterFactory implements PresenterFactory<TestView, TestPresenterImpl> {
#Override
public TestPresenterImpl create() {
return new TestPresenterImpl();
}
}
But I still don't like:
the circular dependency between View and Presenter;
the use of raw types: actually, if you blindly use View<?> and Presenter<?> in their respective interface declarations, then again it won't compile (TestPresenterFactory will fail).
--- edit ---
So how about this to fix the last 2 points, along with your original issue:
interface Presenter<P extends Presenter<P, V>, V extends View<P, V>> {
}
interface View<P extends Presenter<P, V>, V extends View<P, V>> {
}
interface PresenterFactory<P extends Presenter<P, V>, V extends View<P, V>> {
P create();
}
interface ViewFactory<P extends Presenter<P, V>, V extends View<P, V>> {
V create(P presenter);
}
interface TestPresenter extends Presenter<TestPresenter, TestView> {}
class TestPresenterImpl implements TestPresenter {
}
interface TestView extends View<TestPresenter, TestView> {}
class TestViewImpl implements TestView {
public TestViewImpl(Presenter<?, ?> presenter) {
}
}
class TestViewFactory implements ViewFactory<TestPresenter, TestView> {
#Override
public TestView create(TestPresenter presenter) {
return new TestViewImpl(presenter);
}
}
class TestPresenterFactory implements PresenterFactory<TestPresenter, TestView> {
#Override
public TestPresenter create() {
return new TestPresenterImpl();
}
}
I've to create a simple self-made ActiveRecord class for my project.
Only stuck on the problem that I have a getModel() in my Player class, which is being extended by a ActiveRecord class.
When I want to use the getModel() method from my ActiveRecord class, I cant use it cause it's not the same type. I don't want to reference Player here, because I want to use multiple models.
Anyone has a solution?
Ok so I got something up:
abstract class ActiveRecord<T> {
private T model;
public T getModel() {
return this.model;
}
}
public class Player extends ActiveRecord<Player> {
}
public class Event extends ActiveRecord<Event> {
}
But when I try to output this.model in my ActiveRecord class, it return null.
What is wrong here?
Your method definition needs to do something like this
public Class<? extends ActiveRecord> getModel();
Meaning of this is that the return type is of class that extends ActiveRecord. When you do this to the child it would return Player.class as Player extends ActiveRecord.
A brief note if getModel return an object of that class then you should remove Class from the method function
public <? extends ActiveRecord> getModel();
So if I understand well you have a super class called ActiveRecord and a subclass Player, which has a method getModel.
If you want to use ActiveRecord as reference type then you need to have a getModel method in that class as well if you want to access that method. If you are never going to instantiate an ActiveRecord as such you can make it abstract and define the getModel method abstract. If you don't have any implementation logic in ActiveRecord you could make it an interface as well.
public abstract class ActiveRecord {
public abstract Model getModel();
}
public class Player extends ActiveRecord {
#Override
public Model getModel() {
...
}
}
You're making life way too hard for yourself. Java already does reflection for you.
class Parent {
// class content
}
class ChildA extends Parent {
// class content
}
class ChildB extends Parent {
// class content
}
Parent firstInstance = new ChildA();
Parent secondInstance = new ChildB();
Class typeOfFirst = firstInstance.getClass();
Class typeOfSecond = secondInstance.getClass();
As for your null pointer error, in Java (Unlike c++ for example) you have to explicitly initialise every variable with new. Just having private T model; doesn't create an instance of it.
I'm working in some GWT application in which I have a hierarchy where I have an abstract presenter with some common functionality of derived classes. Something like:
public abstract class MyAbstractPresenter<T extends MyAbstractPresenter.CustomDisplay> extends Presenter<T>
{
public interface CustomDisplay extends View
{
//some methods
}
//I want to inject this element
#Inject
private CustomObject myObj;
public MyAbstractPresenter(T display)
{
super(display);
}
}
All the subclasses get injected properly. However, I want to be able to inject that particular field without having it to add it in the constructor of the subclasses. I tried to do field injection as you see , but it doesn't work as it is the subclasses the one that get injected.
Is there a proper way to achieve this Injection without letting the subclasses know about the existence of the field?
Apparently, as for the moment, there is no support for this type of behavior in GIN. A workaround would be to inject the required field in the concrete classes constructors even when they don't need it. Something like:
public abstract class MyAbstractPresenter<T extends MyAbstractPresenter.CustomDisplay> extends Presenter<T>
{
public interface CustomDisplay extends View
{
//some methods
}
//I wanted to inject this element
private final CustomObject myObj;
public MyAbstractPresenter(T display, CustomObject obj)
{
super(display);
myObj = obj;
}
}
Then in any class that extends this abstract implementation, I would have to pass it on construction.
public abstract class MyConcretePresenter extends MyAbstractPresenter<MyConcretePresenter.CustomDisplay>
{
public interface CustomDisplay extends MyAbstractPresenter.CustomDisplay
{
//some methods
}
#Inject //it would get injected here instead.
public MyConcretePresenter(CustomDisplay display, CustomObject obj)
{
super(display, obj);
}
}
I have this super class which extends from another class
public abstract class AbstractDOEMessageFinderAction extends BasicObjectFinder {
public Object performBasicSearch() {
// works fine because getQuery is defined in BasicObjectFinder
return getQuery();
}
The other class is ISIRFinderAction which extends from AbstractDOEMessageDashboardAction
ISIRFinderAction extends AbstractDOEMessageDashboardAction {
// My aim is to make sure this method works so that I will make
// the super class's performBasicSearch() method abstract.
public Object performBasicSearch() {
// this one doesnt even compile but it extends AbstractDOEMessageDashboardAction
// which in turn extends BasicObjectFinder
return getQuery();
}
}
Am I missing something? Why is getQuery not working. I thought it would search it in the class hierarchy.
The second class extends AbstractDOEMessageDashboardAction not AbstractDOEMessageFinderAction.
Does AbstractDOEMessageDashboardAction also extend BasicObjectFinder?
(Note, AbstractDOEMessageDashboardAction is ofcourse not the same as AbstractDOEMessageFinderAction).