【问题标题】:How does a method in a parent call a method in a child?父级中的方法如何调用子级中的方法?
【发布时间】:2016-05-11 16:36:03
【问题描述】:

我有一个父类和一个子类。

父类有两个子类覆盖的方法。

这是一个例子:

public class May11 extends May11Parent
{
    public void m1()
    {
        super.m1();
        System.out.println("3");
    }

    public void m2()
    {
        super.m2();
        System.out.println("4");
    }

}

public class May11Parent
{
    public void m1()
    {
        System.out.println("1");
        m2();
    }

    public void m2()
    {
        System.out.println("2");
    }

}

然后我有一个带有父引用的子对象(子类中的主方法)。我执行m1(),我知道它会转到孩子的m1() 的身体。孩子打电话给家长。家长致电m2()。神奇的是,子和父的 m2() 方法都被执行了。

我的想法是被解雇的是父母的m2()。如果不是父母,那就是孩子!

我认为这可能与多态性有关,但我什至尝试了一个带有子引用的子对象,结果是一样的。我不明白发生了什么事。有什么想法吗??

这是一个不错的截图:

【问题讨论】:

  • m1() 调用m2() 时,由于多态性,只调用了孩子的m2()。但是孩子的m2()super.m2() 语句调用父母的m2()。因此也被称为。
  • 在学习编程时需要理解一件重要的事情:没有魔法。对于大多数事情,都有很好的确定性解释。所以新手的教训可以是:如果你观察到某些东西,试着想出解释所观察到的东西的想法(而不是假设某些东西“神奇地坏了”)。
  • @Codebender 知道这是什么!我得到它! :D
  • @Jägermeister 我正在使用“魔术”来准确指出我丢失的位置。当然,我只是想了解没有任何问题!

标签: java inheritance polymorphism


【解决方案1】:

这里没有魔法。

第一:

引用对象的变量类型仅限制在该位置“可见”的方法。实现仍然由被引用的对象实例决定。

(假设您的子类 (May11) 正在指定一个额外的 m3() 方法。从具有父类类型 (May11Parent) 的变量中,这将是不可调用的。)

第二:

从代码中可以很容易地确定调用顺序:

最初,假设您的对象引用绑定到变量var
May11 类型或May11Parent 类型之一)

  1. 致电var.m1()
    这会调用 May11.m1(),因为对象实例是 May11class 之一。
  2. m1()正在打电话给super.m1()
    这会执行May11Parent.m1()
  3. May11Parent.m1() 正在打印“1
  4. May11Parent.m1() 致电m2()
    由于对象实例是May11 类型一,因此正在执行May11.m2()
  5. May11.m2() 正在呼叫super.m2()(这是May11Parent.m2()
  6. May11Parent.m2() 正在打印“2”并返回
  7. 返回May11.m2() 下一条语句正在打印“4”并返回
  8. 返回May11Parent.m1() 这是返回
  9. 返回May11.m1() 下一条语句正在打印“3”并返回

所有的结果都是应用解析重载方法的规则。

【讨论】:

    【解决方案2】:

    这称为运行时多态动态方法分派,在Java The Complete Reference(第9版,第178页)中说:

    当通过超类引用调用被覆盖的方法时,Java 会根据调用发生时所引用对象的类型来确定要执行该方法的哪个版本。

    在您的示例中(我想这是令人困惑的部分):

    public class May11Parent
    {
        public void m1() {
            System.out.println("1");
            m2();
        }
    // ...
    

    当您在 m1() 中调用 m2()Java 将根据您的对象类型决定调用哪个方法在运行时,因为 xMay11的类型,子类的m2()会被调用。

    如果您知道这一点并遵循流程,您最终会得到输出:1 2 4 3

    【讨论】:

      【解决方案3】:

      这是由于多态性造成的,如果不清楚一步一步发生了什么,我建议您使用带有 Toogle 断点的调试器 我不知道您使用的是哪个 IDE,但是您的 IDE 中肯定也有这个选项。 我使用 Eclipse,在 Eclipse 中的工作方式如下: 右键单击要逐步执行的行,然后单击“Toogle Breakpoint” 然后点击“Degub As”->“Java application” 在屏幕顶部,一个黄色箭头将变为已启用,并具有“步入”功能 通过单击它,您可以逐步了解您的程序正在做什么,我发现这非常有用,可以帮助您更好地理解代码中发生的事情。

      【讨论】:

      • 这并没有解释发生了什么,它只是告诉作者如何调试以遵循代码。我将其投票为“不是答案”。
      • 对于初学者来说真的很有用,你可以检查变量的值一步步变化这解释了发生了什么而不是为什么会发生,要知道为什么会发生你只需要学习,但我认为这是理解应用于实践的理论的好方法
      • 如果不是答案,请将其发布在评论而不是答案中。它是否“有用”并不重要,如果它不是答案,那就不是答案。
      • 对不起,伙计,但请保持冷静......我是 Stackoverflow 的初学者,顺便说一句,问题是“我不明白发生了什么。有什么想法吗?”所以这是一个答案,下次我会评论......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-03
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多