我试图实现并覆盖具有不同返回类型的方法,而不必强制转换返回类型。
public abstract class A {
public abstract Object getValue(String content);
}
public class B extends A {
public String getValue(String content) {...}
}
public class C extends A {
public int getValue(String content) {...}
}
public class D extends A {
public boolean getValue(String content) {...}
}
// Main loop:
for (A a : allAs)
{
// I want to use the method getValue() and corresponding to the type return a String, int or boolean without casting the return type
}
我的问题: 是否有可能在不被迫施放的情况下返回不同的类型? 抽象方法如何解决问题?
我认为必须有一个解决方案,因为编译器应该知道返回类型......
答案 0 :(得分:15)
在您的示例中,类C
和D
将无法编译。被覆盖的方法违反了Liskov substitution principle,也就是说,它们的返回类型与它们的父类不兼容。只要您愿意放弃使用原语作为返回类型,您可以使用泛型完成您想要完成的任务。
abstract class A<T> {
public abstract T getValue(String content);
}
class B extends A<String> {
public String getValue(String content) { }
}
class C extends A<Integer> {
public Integer getValue(String content) { }
}
class D extends A<Boolean> {
public Boolean getValue(String content) { }
}
答案 1 :(得分:3)
您所描述的内容通常是不可能的。但是,如果子类返回超类方法返回的“较窄”子类型,则称为“协变返回类型”,并且自JDK 1.5起允许在Java中使用。但是,根据您的示例,我不认为协变回报是您正在寻找的。 p>
我假设你想要的是
for (A a : allAs)
{
String b = a.getValue();
int c = a.getValue();
}
这里的问题当然是编译器无法在编译时知道这两个语句中的哪一个是正确的,并且它们都不能正确。
答案 2 :(得分:2)
你可以使用泛型。
public abstract class A<T> {
public abstract T getValue(String content);
}
public class B extends A<String> {
public String getValue(String content) {...}
}
etc ... int不能作为返回类型,但Integer会。
我没有在编译器上打字,所以可能存在拼写错误......
如Jim和Chris所述,如果你在As上循环,你只能获得“A”结果,即Object。
答案 3 :(得分:0)
在您的示例中,class B
的定义没问题,因为String
是Object
的子类。另外两个不会编译,因为它们是原始类型。您可以使用Integer
和Boolean
返回来替换它们来解决这个问题。
至于你的主循环,如果你作为A
的引用迭代它们,你将只能使用A
的方法定义,它返回{{1 }}