我有类似于此设置的内容:
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??
}
我如何做到这一点?
答案 0 :(得分:6)
首先:
if (b instanceof Extended){
b = (Extended) b;
}
绝对没有。你基本上是在说b = b
,它什么也没说。您甚至没有更改参考。
其次,getApple()
将始终动态绑定,并且应始终调用“扩展的apple” - 假定子类真正扩展了基类,并且该方法被真正覆盖。
基本上您需要做的是为了实现正确的getApple()
行为:
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将从继承层次结构的底部开始,并调用适当的方法。当您引用字段时,它会使用指针的类而不是向上遍历类层次结构来解析值。字段引用的行为与您所看到的相符,这就是我要求澄清/验证的原因。