Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incompatible return type when overriding methods of Generic classes in Java

I was playing around with generics, and I found a problem I really can't figure out. Please take a look at this code:

class Operation<R> {
}

class P<O extends Operation<R>, R> {
}

class MyResource {
}

class MyO extends Operation<MyResource> {
}

class MyP extends P<MyO, MyResource> {
}

abstract class A<R> {
    abstract P<Operation<R>, R> doIt();
}

class B extends A<MyResource> {
    @Override
    MyP doIt() {
    /*
        the compiler is complaining about the above line:
        The return type is incompatible with A<MyResource>.doIt()
    */
        return null;
    }
}

So basically, MyP is a subclass of P<MyO, MyResource> which in turn is a subclass of P<Operation<MyResource>, MyResource>. In other words, we are returning a subclass of A.doIt return type in B.doIt. But nevertheless, the compiler is complaining.

Can you help me to understand this ? Thanks.

like image 841
randomdev7u81 Avatar asked Mar 13 '14 15:03

randomdev7u81


People also ask

Why is my return type incompatible in Java?

Since, boolean </: void (read: boolean isn't subtype of void ), compiler raises the "return type incompatible" error. This is neither overloading nor overriding. We cannot overload on the return type and we cannot override with different different return types ( unless they are covariant returns wef Java 1.5 ).

How to override a method in a class?

When we are overriding a method then we must keep three things in mind. The method in the subclass must have the same name as the method present inside the superclass. The method in the subclass should have the same number of parameters.

Can a sub class declare a method with the same signature?

The sub class cannot declare a method with the same name of an already existing method in the super class with a different return type. However, the subclass can declare a method with the same signature as in super class. We call this "Overriding".

Can We have multiple return types in Java?

We cannot overload on the return type and we cannot override with different different return types ( unless they are covariant returns wef Java 1.5 ). Thanks for contributing an answer to Stack Overflow!


1 Answers

The problem is that MyP is a P<MyO,>, which is not the same as a P<Operation<MyResource>,> (even though it does inherit it).
You need to change the abstract method's return type to be covariant in that parameter:

abstract class A<R> {
    abstract P<? extends Operation<R>, R> doIt();
}

Now, MyP is convertible to the base return type, so everything works fine.

like image 144
SLaks Avatar answered Nov 14 '22 23:11

SLaks