例如,如果我们有一个类Person
而一个类Student
扩展了Person。
我们可能有:
public interface PersonQueryBuilder<T extends Person> {
PersonQueryBuilder<T> withName(String name);
PersonQueryBuilder<T> withAgeBetween(int from, int to);
List<T> getResultList();
}
public interface StudentRepository<T extends Student> extends PersonQueryBuilder<T> {
StudentRepository studying(Course course);
}
那么为什么当我有一个StudentRepository时,withName()和withAgeBetween()方法都返回一个PersonQueryBuilder而不是StudentRepository?这非常烦人。有没有“优雅”的方法来解决这个问题?
答案 0 :(得分:4)
interface StudentRepository<T extends Student> extends PersonQueryBuilder<T> {
StudentRepository<T> studying(Course course);
StudentRepository<T> withName(String name);
StudentRepository<T> withAgeBetween(int from, int to);
}
您可以在子界面中重新声明方法。现在,StudentRepository
的实施者需要为这些方法返回StudentRepository
,但实现仍可以多态地用作PersonQueryBuilder
。
答案 1 :(得分:3)
这很有趣。我提出以下(丑陋的?)解决方案,不要求你重新定义接口中的方法,如Mark的答案那样:
interface PersonQueryBuilder<T extends Person, U extends PersonQueryBuilder<T,U>> {
U withName(String name);
U withAgeBetween(int from, int to);
}
interface StudentRepository extends PersonQueryBuilder<Student, StudentRepository> {
StudentRepository studying(Course course);
}
此外,您在原始类型中使用原始类型作为with
方法的当前实现的结果。
答案 2 :(得分:2)
首先,因为您使用原始类型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);
}