randomdev7u81
randomdev7u81

Reputation: 75

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.

Upvotes: 5

Views: 1895

Answers (2)

Judge Mental
Judge Mental

Reputation: 5239

Your claim that P<MyO, MyResource> is a subclass of P<Operation<MyResource>, MyResource> is incorrect. These kinds of relations do not hold in Java, and the reason is that the generic class could use its type parameter in either covariant or contravariant fashion (or both). If the usage is anything but strictly covariant, the automatic subtype relationship you propose would be unsound. @SLaks has the right idea.

Upvotes: 2

SLaks
SLaks

Reputation: 887453

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.

Upvotes: 6

Related Questions