如何创建返回类型为超类任意子类的方法

3

预先准备的信息。

public abstract class Person {}
public class A extends Person{}
public class B extends Person{}
public class C extends Person{}

public X getPersonByType(String type){
    //This Method will return either A or B or C based on type
    //what should X be ?    
}

我需要创建一个方法,它接受一个字符串并返回一个Person子类型的对象。
更多信息。 每个A、B、C类都有一个公共属性List roles。由于我需要这些属性在JPA many to many表中具有唯一名称,因此不能将它们移到Person类中。
现在,如果可能的话,我不想返回person,因为我无法访问roles属性(Person不知道它)。如果可能的话,我也希望找到一种解决方案,不需要我进行强制转换或使用instanceOf。
P.S 尝试过<? extends Person>,但Eclipse给出了错误提示“方法的返回类型缺失”。

9
使其返回 Person - Sotirios Delimanolis
请查看泛型通配符相关的文档。 - Justin
2
@gangqinlaohu:这里没有迹象表明泛型是合适的。 - Jon Skeet
请查看添加的更多信息。谢谢。 - SpartanElite
4个回答

3

public Person getPersonByType(String type) 应该可以很好地工作,因为所有的返回类型都继承自 Person

如果您想避免在调用此方法后进行 instanceof 检查,则还可以添加一个额外的类参数:

public <T extends Person> T getPersonByType(String type, Class<T> type) {
   ...
   // cast result to T
}

使用这种方法,您可以直接将返回类型分配给子类:
C c = getPersonByType("c", C.class);

请注意,如果您传递一个字符串和一个不匹配的类参数,这可能会导致ClassCastExceptions


正确的声明应该是:public <T extends Person> T getPersonByType(String type, Class<T> type) {...} - JMess

1
public Person getPersonByType(String type){
// analyze type and return appropriate instance...
    if ("A instance".equals(type)) {
        return new A();
    }
...

}

1

X 应该改为 Person

因为 Person 是一个抽象类,无法实例化,它将始终返回你的子类型之一。

如果需要知道从调用方法返回的 getPersonByType 的值,可以使用 instanceof 运算符。


1
你应该返回 人物 X。由于 人物 是一个抽象类型,因此它不能被实例化。你可以将 人物 X 作为一个 引用,它应该指向在你的情况下的任何一个具体实现人物 的对象,它们是 A, BC。这就是运行时多态性的优美之处。根据你在运行时的输入,它将创建任何一个 A, B 或者 C 类的对象,并使用引用 X 指向该对象。我建议你阅读工厂设计模式,这将为你提供关于这种设计如何在实际场景中工作的更多信息。

好建议。我过于考虑使用泛型,但这是一个不错的简单解决方案。谢谢,它起作用了。 - SpartanElite
我有类似的代码,当我返回1个元素的抽象超类型时它可以工作。但是,当我尝试返回List<Person>时,它就不起作用了。我得到了一个编译错误,指出:即使A扩展了Person,也需要List<Person>,而不是List<A>。我还尝试在我的方法中添加<T extends Person> List<T>,然后我得到了消息:需要List<T>,但发现了List<A>... 你有什么想法如何使用集合来解决这个问题? - wheeleruniverse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接