I have some classes that look like this:
MODEL
public abstract class BaseEntity<O extends Object> { ... }
public class Person extends BaseEntity<Person> { ... }
COMMAND
public abstract class BaseCommand<BE extends BaseEntity<BE>> { ... }
public class PersonCommand extends BaseCommand<Person> { ... }
SERVICE
public interface BaseService<BE extends BaseEntity<BE>> {
public BE create(BaseCommand<BE> command);
}
public interface PersonService extends BaseService<Person> { ... }
SERVICE IMPL
public abstract class BaseServiceImpl<BE extends BaseEntity<BE>> implements BaseService<BE> { }
public class PersonServiceImpl extends BaseServiceImpl<Person> implements PersonService {
public Person create(PersonCommand personCommand) { ... }
}
The PersonServiceImpl class won’t compile. It’s not recognizing that the create() method is implementing the create() method from the BaseService interface. Can anyone tell why PersonCommand isn’t being recognized as a BaseCommand<BE> (in the parameter list)?
When overriding, method parameters are not covariant (that is, subclasses have to accept a type that the superclass also accepts, not anything narrower).
This is because people can use your
PersonServiceImplvia thePersonServiceinterface, which will accept an argument of typeBaseCommand<Person>that is not necessarily aPersonCommand(imagine if you created a second class that extendedBaseCommand<Person>).If you make your method take a parameter of type
BaseCommand<Person>, your code should compile correctly.