Java 扩展接口时返回子元素列表
我正在开发一个库,在将返回类型重写为子元素列表时遇到了一个问题 一开始是这样的,Java 扩展接口时返回子元素列表,java,generics,overloading,generic-list,Java,Generics,Overloading,Generic List,我正在开发一个库,在将返回类型重写为子元素列表时遇到了一个问题 一开始是这样的, Class Student { } public interface A { public Student isCurrentStudent(String name); public List<Student> getStudentList(); } public interface B extends A {
Class Student {
}
public interface A {
public Student isCurrentStudent(String name);
public List<Student> getStudentList();
}
public interface B extends A {
public List<Student> getColleges();
public Student getBestFriend();
}
B bObject = getBObject();
List<Student> studentList = bObject.getColleges();
D dObject = getDObject();
List<SeniourStudent> seniorStudentList = dObject.getColleges();
班级学生{
}
公共接口A{
公共学生是当前学生(字符串名称);
公共列表getStudentList();
}
公共接口B扩展了{
公开大学名单();
公立学生获得最佳朋友();
}
然后我想介绍SeniourStudent类和access SeniourStudent的API,所以我提出了以下建议:
Class SeniorStudent extends Student{
}
public interface C extends A {
public SeniorStudent isCurrentStudent(String name);
public List<SeniorStudent> getStudentList();
public void addStudent(Attributes s);
}
public interface D extends B,C {
public List<SeniorStudent> getColleges();
public Student getBestFriend();
}
班高年级学生扩展学生{
}
公共接口C扩展了{
公共高级学生是当前学生(字符串名称);
公共列表getStudentList();
公立学校学生;
}
公共接口D扩展了B,C{
公开大学名单();
公立学生获得最佳朋友();
}
问题从接口C和D开始。因为java支持协变返回类型,所以C的第一个方法不会给出错误。但是当返回类型为“List”时,这就产生了麻烦。因此,我已将上述接口更改为使用泛型
public interface A <T extends Student> {
public Student isCurrentStudent(String name);
public List<T> getStudentList();
}
public interface B<T extends Student> extends A<T> {
public List<T> getColleges();
public Student getBestFriend();
}
public interface C extends A<SeniorStudent> {
public SeniorStudent isCurrentStudent(String name);
public List<SeniorStudent> getStudentList();
public void addStudent(Attributes s);
}
public interface D extends B<SeniorStudent>,C {
public List<SeniorStudent> getColleges();
public SeniorStudent getBestFriend();
}
公共接口A{
公共学生是当前学生(字符串名称);
公共列表getStudentList();
}
公共接口B扩展了{
公开大学名单();
公立学生获得最佳朋友();
}
公共接口C扩展了{
公共高级学生是当前学生(字符串名称);
公共列表getStudentList();
公立学校学生;
}
公共接口D扩展了B,C{
公开大学名单();
公共高年级学生getBestFriend();
}
我相信这个设计是可以改进的,这样B类的实现者可以被限制为只使用Student类
我最终想要的是,提供干净的API,可以像这样使用
Class Student {
}
public interface A {
public Student isCurrentStudent(String name);
public List<Student> getStudentList();
}
public interface B extends A {
public List<Student> getColleges();
public Student getBestFriend();
}
B bObject = getBObject();
List<Student> studentList = bObject.getColleges();
D dObject = getDObject();
List<SeniourStudent> seniorStudentList = dObject.getColleges();
B bObject=getBObject();
List studentList=bObject.getColleges();
D dObject=getDObject();
List seniorStudentList=dObject.getColleges();
如果在返回类型是子元素列表时有一种方法覆盖它,那么整个问题就可以解决了
因为我的实际代码要大得多,所以我在这里使用了一个简单的示例来描述这个问题。希望它足够清晰
编辑 为B引入一个BS超类型将解决这个问题。但这是更干净的方式吗
public interface A <T extends Student> {
public Student isCurrentStudent(String name);
public List<T> getStudentList();
}
public interface BS<T extends Student> extends A<T> {
public List<T> getColleges();
public Student getBestFriend();
}
public interface B extends BS<Student> {
public List<Student> getColleges();
public Student getBestFriend();
}
public interface C extends A<SeniorStudent> {
public SeniorStudent isCurrentStudent(String name);
public List<SeniorStudent> getStudentList();
public void addStudent(Attributes s);
}
public interface D extends BS<SeniorStudent>,C {
public List<SeniorStudent> getColleges();
public SeniorStudent getBestFriend();
}
公共接口A{
公共学生是当前学生(字符串名称);
公共列表getStudentList();
}
公共接口BS扩展了{
公开大学名单();
公立学生获得最佳朋友();
}
公共接口B扩展了BS{
公开大学名单();
公立学生获得最佳朋友();
}
公共接口C扩展了{
公共高级学生是当前学生(字符串名称);
公共列表getStudentList();
公立学校学生;
}
公共接口D扩展了BS,C{
公开大学名单();
公共高年级学生getBestFriend();
}
谢谢,我有点不明白你到底想做什么。但我想,您的问题可以通过不使接口
C
和D
通用化来解决。您可以使用如下界面:
interface A<T extends Student> {
public T isCurrentStudent(String name);
public List<T> getStudentList();
}
interface B<T extends Student> extends A<T> {
public List<T> getColleges();
}
interface C extends B<Student> {
public Student isCurrentStudent(String name);
public List<Student> getStudentList();
public List<Student> getColleges();
}
interface D extends B<SeniorStudent> {
public SeniorStudent isCurrentStudent(String name);
public List<SeniorStudent> getStudentList();
public List<SeniorStudent> getColleges();
}
接口A{
公共T是当前学生(字符串名称);
公共列表getStudentList();
}
接口B扩展了A{
公开大学名单();
}
接口C扩展了B{
公共学生是当前学生(字符串名称);
公共列表getStudentList();
公开大学名单();
}
接口D扩展了B{
公共高级学生是当前学生(字符串名称);
公共列表getStudentList();
公开大学名单();
}
然后,让你的班级分别为
Student
和seniordstudent
实现接口C
和D
。这是我能想到头顶的唯一方法。看看你是否能接受这个,否则我们可以试着在这方面做进一步的即兴创作。正如Plínio Pantaleão在评论中所说(或者实际上,我想说),你可以定义接口来返回列表你的基本接口(a和B)可以返回列表你可能是指列表对于接口D,我也想从B继承方法。对不起,我可能不清楚这个问题。我指的是这个问题。根据问题,它是D和B。根据你的答案,它是D和C。正如你所看到的,我正在覆盖getColleges()方法,而B(wrt qustion或C wrt answer)包含更多不需要覆盖的方法。@DarRay那么你想让我答案中的接口C
没有getColleges()
方法吗?我还不清楚你到底想要什么。我无法连接我的答案中的C
与问题中的B
的相似之处。我之前对你的答案有点困惑,但如果我理解正确,如果我为B(wrt问题)引入一个child类(比如childB),它将与你的答案相匹配。所以我应该实现childB和D,而不是实现B和D。我确实这样想,但是我们不能有很多清晰的设计吗?事实上我已经在做同样的事情了,不是吗?我使用,public List getColleges();在创建对象时强制定义类型T。我这样做是因为我有更多的方法必须返回Student或SeniourStudent列表(取决于B或D),并且希望所有这些方法只返回一个类型,该类型定义了创建对象的时间。我用需要实现的预期行为更新了问题。你有什么建议吗?@DarRay我用编辑更新了答案,但可能有点棘手,因为一个方法是用不同的返回类型继承的……是的,还有其他方法是从B继承到D的。我对问题进行了编辑,添加了“public SeniorStudent getBestFriend();”来表示这些方法。我目前的设计与你们的答案有些相似,也和@RohitJain所说的一致。基本上,我所做的是引入一个新的interf
import java.util.List;
public class StudentsReturnTypesTest
{
public static void main(String[] args)
{
B bObject = getBObject();
List<Student> studentList = bObject.getColleges();
bObject.methodThatWasInB();
D dObject = getDObject();
List<SeniorStudent> seniorStudentList = dObject.getColleges();
dObject.methodThatWasInB();
}
private static D getDObject() { return null; }
private static B getBObject() { return null; }
}
interface A<T extends Student> {
public Student isCurrentStudent(String name);
public List<T> getStudentList();
}
interface AS extends A<Student> { }
interface B extends AS, AdditionalMethodsThatHaveBeenInB {
public List<Student> getColleges();
}
interface AdditionalMethodsThatHaveBeenInB {
void methodThatWasInB();
}
interface C extends A<SeniorStudent> {
public SeniorStudent isCurrentStudent(String name);
public List<SeniorStudent> getStudentList();
public void addStudent(Attributes s);
}
interface D extends C, AdditionalMethodsThatHaveBeenInB {
public List<SeniorStudent> getColleges();
}
interface Attributes {}
interface Student {}
interface SeniorStudent extends Student {}