Для одного, потому что вы используете необработанный тип PersonQueryBuilder в качестве возвращаемого типа.T
не отображается в этом типе, так почему конкретный T
имеет значение?Поэтому первое улучшение:
PersonQueryBuilder<T> withName(String name);
PersonQueryBuilder<T> withAgeBetween(int from, int to);
Следующая проблема связана с тем, что StudentRepository не обязательно должен быть единственным PersonQueryBuilder для студентов, поскольку было бы совершенно законно объявить:
interface UniversityRepository<T extends Student> extends PersonQueryBuilder<T> { }
Итак, по вашей логике, тип возвращаемого значения должен быть StudentRepository или UniversityRepository?Или как-то оба?Компилятор не может знать ваше намерение, поэтому должен указать, что вы хотите, например, используя ковариантный тип возвращаемого значения:
public interface StudentRepository<T extends Student> extends PersonQueryBuilder<T> {
@Override
StudentRepository<T> withName(String name);
@Override
StudentRepository<T> withAgeBetween(int from, int to);
StudentRepository<T> studying(Course course);
}
Очевидный недостаток этого подхода заключается в том, что вам приходится повторять все унаследованные методы.Вы можете обойти это с помощью параметра типа для реального хранилища:
public interface PersonQueryBuilder<T extends Person, R extends PersonQueryBuilder<T, R>> {
R withName(String name);
R withAgeBetween(int from, int to);
List<T> getResultList();
}
и
public interface StudentRepository<T extends Student, R extends StudentRepository<T, R> extends PersonQueryBuilder<T, R> {
R studying(Course course);
}