重写 Java 中的方法,然后将对象强制转换为父类行为



我有一个父类 A 和一个子类 B 和 B 覆盖来自 A 的方法 f。

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(b.f()); //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,因为方法调用是多态的

当你投射实例时,你只是暗示它可能是来自超类的实例,但该实例的内部实现不会改变,这就是你得到这个结果的原因!

打个比方,如果你把美国人的面具戴在一个英国人身上(演员),那个人仍然是英国人(继承),但如果你让那个人说话(调用一种方法),你仍然会听到英国口音,而不是美国口音(内部实施最终才是最重要的):-)

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

最新更新