Java继承问题

时间:2009-07-28 19:22:14

标签: java inheritance

我有类似于此设置的内容:

public class Base {
    public String getApple() {return "base apple"};
}

public class Extended extends Base{
    public String getApple() {return "extended apple"};
}

代码中的其他地方我有这个:

{
    Base b = info.getForm();

    if (b instanceof Extended){
        b = (Extended) b;
    }

    System.out.println(b.getApple()); // returns "base apple" even when if clause is true why??

}

我如何做到这一点?

8 个答案:

答案 0 :(得分:6)

首先:

if (b instanceof Extended){
    b = (Extended) b;
}

绝对没有。你基本上是在说b = b,它什么也没说。您甚至没有更改参考。

其次,getApple()将始终动态绑定,并且应始终调用“扩展的apple” - 假定子类真正扩展了基类,并且该方法被真正覆盖。

基本上您需要做的是为了实现正确的getApple()行为:

  • 删除if子句。它什么都不做。
  • 确保您的类确实正在扩展基类
  • 确保getApple()方法覆盖基类方法。 (如果您不确定,请使用@override注释)

答案 1 :(得分:4)

如上所述,您的代码将无法编译,这使我认为您的问题在其他地方。您的返回语句末尾没有分号。相反,它们出现在}之后。你可能有其他一些问题(也许你的子类拼写错误的getApple()),但是你仍在使用你的旧类文件,因为你的新东西没有编译。

此代码有效:

class Base {
   public String getApple() { return "base apple"; }
}
class Extended extends Base {
  public String getApple() { return "extended apple"; }
}
public class Test {
  public static void main(String[] args) {
     Base b = new Extended();
     System.out.println(b.getApple());
  }
}

控制台:

#javac Test.java
#java Test
extended apple

答案 2 :(得分:1)

首先,如果永远不需要块。它基本上是一种无操作。

其次,这不是你真正的代码,因为它甚至不编译。你在返回语句后丢失了分号。

我怀疑你的问题是你的真实代码有一个拼写错误,使两个getApple方法的签名不同。这意味着Extended有两种方法:一种是从Base继承的,另一种是具有不同签名的方法。由于您使用Base.getApple方法的签名进行调用,因此您始终会获得该行为。这只是猜测,因为您发布的代码没有显示您描述的问题。

答案 3 :(得分:1)

Yuval是正确的,你if块中的演员表无效。您可以尝试将最后一个语句与if

结合使用
if (b instanceof Extended)
{
    // Prints "extended apple" if reached.
    System.out.println(((Extended)b).getApple()); 
}

答案 4 :(得分:1)

@Override添加到子类中的方法并重新编译。这将帮助您了解您是否实际上没有覆盖您认为的方法。

public class Base {
    public String getApple() {return "base apple";}
}

public class Extended extends Base{
    @Override
    public String getApple() {return "extended apple";}
}

答案 5 :(得分:0)

获得该行为的唯一方法是在扩展类中返回super.getApple(),这实际上与首先不覆盖它相同。这可能有用的唯一方法是传入一个参数来决定返回哪个。不是说好的设计......

忘了提及,正如尤瓦尔所说,演员对这个对象毫无作为。

答案 6 :(得分:0)

您应该调查构建从info.getForm()返回的实例的内容。您可能希望创建Base抽象以防止它被实例化,并且您将很快看到构造发生的位置。

答案 7 :(得分:0)

您确定问题中提供的代码示例是否与您使用的代码完全匹配?我问的原因是当您使用对象指针访问公共 FIELD 而不是公共 METHOD 时,您所描述的行为就会发生。

例如:

public class BaseClass {
    public String baseField;

    public BaseClass() {
        baseField = "base";
    }

    public String getBaseField() {
        return baseField;
    }
}

public class SubClass extends BaseClass {
    public String baseField;

    public SubClass () {
        baseField = "sub";
    }

    public String getBaseField() {
        return baseField;
    }
}

public class MainClass {
    public static void main(String[] args) {
        BaseClass baseObject = new BaseClass();
        SubClass subObject = new SubClass();
        System.out.println(baseObject.getBaseField());
        System.out.println(subObject.getBaseField());
        System.out.println(baseObject.baseField);
        System.out.println(subObject.baseField);
        System.out.println(((BaseClass)subObect).getBaseField());
        System.out.println(((BaseClass)subObect).baseField);
    }
}

将打印出来:

base
sub
base
sub
sub
base

调用方法时,JVM将从继承层次结构的底部开始,并调用适当的方法。当您引用字段时,它会使用指针的类而不是向上遍历类层次结构来解析值。字段引用的行为与您所看到的相符,这就是我要求澄清/验证的原因。