9

我正在尝试实现和覆盖具有不同返回类型的方法,而不必强制转换返回类型。

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
}

我的问题:是否可以在不强制转换的情况下返回不同的类型?抽象方法是如何解决问题的?

我认为必须有一个解决方案,因为编译器应该知道返回类型......

4

4 回答 4

19

在您的示例中,类CD不会编译。它们中的重写方法违反了Liskov 替换原则,也就是它们的返回类型与它们的父类不兼容。只要您愿意放弃使用原语作为返回类型,就可以使用泛型来完成您想要做的事情。

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) { }
}
于 2013-02-23T06:46:48.610 回答
3

你所描述的一般是不可能的。但是,如果子类返回超类方法返回的“更窄”子类型,则这称为“协变返回类型”,并且从 JDK 1.5 开始在 Java 中是允许的。但是,根据您的示例,我认为协变回报不是您要寻找的。

我假设你想要的是

for (A a : allAs)
{
    String b = a.getValue();
    int    c = a.getValue();
}

当然,这里的问题是,编译器无法在编译时知道这两个语句中的哪一个是正确的,而且它们也不可能都是正确的。

于 2013-02-23T06:43:07.403 回答
2

你可以使用泛型。

public abstract class A<T> {
   public abstract T getValue(String content);
}

public class B extends A<String> {
   public String getValue(String content) {...}
}

等等... int 不能作为返回类型,但 Integer 可以。

我没有在编译器上打字,所以可能有错别字......

正如 Jim 和 Chris 所指出的,如果您在 As 上循环,则只能得到“A”结果,即 Object。

于 2013-02-23T06:54:30.493 回答
1

在您的示例中,定义class B是可以的,因为String它是Object. 另外两个不会编译,因为它们是原始类型。您可以将它们替换为IntegerBoolean返回以解决该问题。

至于您的主循环,如果您将它们作为对 的引用进行迭代A,您将只能使用A' 方法的定义,该方法返回Object.

于 2013-02-23T06:46:58.977 回答