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

重写java中的方法,然后将对象强制转换为父类行为,java,inheritance,Java,Inheritance,我有一个父类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

我有一个父类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”)


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

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

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

A=(A)b


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

这是一个设计决策。您已经创建了一个类型为“B”的对象,所以它就是这样


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

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

这是多态性的基础 它应该是这样工作的。

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

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

所以你所观察到的行为和预期的一样,它就是这样设计的。这绝对不是限制

希望这能有所帮助。

如果要在
a
中执行
f
的实现,您需要一个
新的a()
。或的可能重复