覆盖java中的方法,然后将对象转换为父类行为

我有一个父类A和一个子类,B和B覆盖了一个方法f,来自A.

public class A { public String f() { return "A"; } } public class B extends A { ... public String f() { return "B"; } public static void main(String[] args) { B b = new B(); A a = (A) b; System.out.println(bf()); //prints: B } } 

我创建了一个类型为B,b的对象,并将其转换为类型A并将其分配给类型为A的变量a,然后在a上调用方法f。 现在我希望调用父类的方法,因为我正在处理类型A的对象,但事实并非如此,它调用方法的b版本(打印“B”而不是“A”)下面的代码)。

为什么会这样? 这是设计决策还是技术限制?

这是多态性的基础

它应该像那样工作。

根据对象实际类型而不是引用它的类型动态地调度(选择/调用)任何方法。

将对象转换为其他类型时,只需使用其他类型引用它。 对象的实际类型不会更改。 (它永远不会改变)。

因此,您正在观察的行为符合预期,并且它的设计就是这样。 这绝对不是限制。

希望这可以帮助。

这是一个设计决定。 你已经创建了一个类型为“B”的对象,这就是它的本质。

当你把它强制转换为A时,你只是告诉解释器,预期在类型A的类中找到的方法可用于B,但由于你有一个B的@Override方法,它将使用它。

A a =(A)b;

通过转换变量a ,引用没有改变,因此仍然调用方法f因为方法调用是多态的

当您转换实例时,您只是暗示它可能是来自超类的实例,但该实例的内部实现不会改变,这就是您获得该结果的原因!

比喻说,如果你在英国人(演员)上使用美国人的面具,那个人仍然是英语(inheritance),但如果你要求那个人说话(称呼一种方法),你仍会听到英国口音,而不是美国人(内部实施最终是重要的):-)

这就是它应该如何工作。 它在B上调用方法,因为这是变量被实例化的方式。 它所分配的变量的类型不会改变a实际上是B类的事实。 大多数语言都是这样的,包括C#。