【问题标题】:Overriding methods in java and then casting object to parent class behavior覆盖java中的方法,然后将对象转换为父类行为
【发布时间】:2014-04-04 23:25:15
【问题描述】:

我有一个父类 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”下面的代码)。

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

【问题讨论】:

标签: java inheritance


【解决方案1】:

这是多态性的基础

它应该是这样工作的。

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

当您将对象转换为另一种类型时,您只需使用另一种类型来引用它。对象的实际类型没有改变。 (而且它永远不会改变)。

因此,您所观察到的行为与预期的一样,并且被设计成那样。这绝对不是限制。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      A a = (A) b;

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2015-11-30
            • 2017-03-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-17
            相关资源
            最近更新 更多