Reputation: 314
I have the following model to make controllers in my application. Obviously, the full model is more complex but I will focus on the only part that is causing me problems:
public abstract AbstractController<T> {
abstract protected Class<T> getType();
}
public ParentController extends AbstractController<Parent> {
@Override
protected Class<Parent> getType() {
return Parent.class;
}
}
Now I would like to extend the Parent object and have a controller for the son, it would look like this:
public SonController extends ParentController {
@Override
protected Class<Son> getType() {
return Son.class;
}
}
The problem is that the method getType() shows incompatibility in compilation (expects the class Parent).
I tried to play around with the generics but I can't find a solution. The method getType is used in several methods from the abstract controller and I would really like to avoid overriding those.
Any ideas would be wellcome.
Upvotes: 8
Views: 105
Reputation: 120848
Generics are invariant to begin with, so Class<Son>
can not be assigned to Class<Parent>
(in your case these are not covariant return types).
But wildcard with an extends-bound (upper bound) makes the type covariant, thus this would solve it:
public abstract class AbstractController<T> {
abstract protected Class<? extends T> getType();
}
public class ParentController extends AbstractController<Parent> {
@Override
protected Class<? extends Parent> getType() {
return Parent.class;
}
}
class SonController extends ParentController {
@Override
protected Class<? extends Parent> getType() {
return Son.class;
}
}
Upvotes: 5
Reputation: 17880
You could change the getType
return Class<? extends T>
.
abstract protected Class<? extends T> getType();
Then ParentController
and SonController
would look like
public class ParentController extends AbstractController<Parent> {
@Override
protected Class<? extends Parent> getType() {
return Parent.class;
}
}
public class SonController extends ParentController {
@Override
protected Class<? extends Parent> getType() {
return Son.class;
}
}
Upvotes: 6