【问题标题】:Why can this object access methods of it's parent class?为什么这个对象可以访问它的父类的方法?
【发布时间】:2017-09-23 23:37:54
【问题描述】:

此问题来自 AP 计算机科学实践测试。

public class Bird
{
    public void act()
    {
        System.out.print("fly"); 
        makeNoise(); 
    }
    public void makeNoise()
    {
        System.out.print("chirp"); 
    }
}

public class Dove extends Bird
{
    public void act()
    {
        super.act(); 
        System.out.print("waddle"); 
    }
    public void makeNoise()
    {
        super.makeNoise(); 
        System.out.print("coo"); 
    }
}

假设以下声明出现在 Bird 或 Dove 以外的类中:

Bird pigeon = new Dove(); 

调用pigeon.act()会打印什么?

我以为答案是“fly chirp”,但教科书上说答案是“fly chirp coo waddle”。我认为“鸽子”只能访问 Bird 中可用的方法?我的印象是,如果用户想要访问 Dove 中的方法,则必须将“pigeon”转换为 Dove。

Bird pigeon = new Bird(); 会给出相同的输出吗? Dove pigeon = new Dove();呢?

【问题讨论】:

  • 任何类都可以使用super关键字显式调用其父方法。
  • 我了解 super 关键字的功能。我的问题是为什么“Bird pigeon”可以访问 Dove 中的方法。我以为“鸽子=新鸽子();”会产生“fly chirp coo waddle”。
  • @CarolineYi 子类继承了其父类的所有实例方法。现在子类可以选择覆盖被覆盖方法的行为。同样使用 super 关键字,它可以访问或调用其超级父类中定义的行为。现在建议您带上笔记本和笔,对您的代码进行试运行。查看方法是如何被调用的。以下答案(包括我的)可能会有所帮助。
  • 只是添加如果您从子类外部查看子类然后,一旦子类继承了一个方法,那么覆盖意味着修改相同继承方法的行为 ,覆盖并不意味着添加额外的方法。它是子类的内部方法,实际上可以通过super.调用超父类方法的行为@
  • @Caroline 如果您的问题得到解决,您可以选择一个已接受的答案,或者让我们知道您的更多疑问。

标签: java inheritance polymorphism superclass


【解决方案1】:

长话短说,当您访问pigeonact 方法时,会调用它对Dove 的覆盖。

我认为“鸽子”只能访问 Bird 中可用的方法?

这当然是正确的,至少在没有应用强制转换的情况下是这样。但是,act 方法在 Bird 类上可用,pigeon 的静态已知类型,所以调用编译得很好。

然而,访问方法只是为了能够调用它们。调用它们时执行的方法是在运行时根据pigeon动态 类型决定的。这就是方法覆盖发挥作用的地方,因为Dove 覆盖了Bird 的方法,但此外它还调用Bird 的方法。这就是代码命中所有四个打印输出的原因。

Bird pigeon = new Bird(); 会给出相同的输出吗?

不,输出会不同,因为在这种情况下,pigeon 的动态和静态类型都是相同的,即Bird,因此只会调用Bird 的实现。

【讨论】:

  • 这也是为什么你不能从构造函数调用可覆盖方法的原因,因为子类可能已经覆盖了它,使你的构造函数变得脆弱并且可能不安全。
【解决方案2】:
  • Dove覆盖Bird 类的方法actmakeNoise。覆盖意味着将方法 visible 的行为更改为子类(在您的情况下为 Dove)。如果方法具有publicprotected 访问修饰符,或者如果它们具有package private 访问修饰符并且子类与超类属于同一个包,则方法对子类可见。
  • pigeonDove 的一个实例。
  • 调用pigeon.act() 会导致调用Dove.act
  • Dove.act 调用 super.actBird.act
  • Bird.act 打印 fly 并在 pigeon 上调用 makeNoise 导致调用 Dove.makeNoise
  • Dove.makeNoise 调用 super.makeNoiseBird.makeNoise
  • Bird.makeNoise打印chirp
  • Dove.makeNoise 在调用super.makeNoice 后打印coo

【讨论】:

    【解决方案3】:

    您在这里体验到的是多态性。而不是直接回答你的各种问题;我将简单地解释您正在观察的情况。

    您在 Dove 实例上调用 act();导致调用 super;打印“飞”。

    然后,该超级方法在“自身”上调用 makeNoise() ...。但正如所说:“本身”是一个鸽子对象;因此你会得到鸽子的噪音! “咕”!

    然后Dove实现结束;并打印“蹒跚”。

    本质是:被调用的方法的确切版本运行时确定并且它 > 取决于调用该方法的对象的确切类型。

    以上内容为您所有提供了您自己回答其他问题所需的信息。从这个意义上说:不要要求答案;要求解释;并用它们自己解决难题!

    【讨论】:

      【解决方案4】:

      根据您的问题“我认为 'pigeon' 只能访问 Bird 中可用的方法?我的印象是,如果用户想要访问 Dove 中的方法,则必须将 'pigeon' 强制转换为 Dove。”这实际上是正确

      让我们尝试在理解中找到mssing链接。

        1234563由于该对象属于Dove,因此它具有从超类继承以及添加的方法。
      1. 另一个重要的一点是所有 overriden 方法只有一个实例。它的 Overriden 意味着相同方法的行为已被修改,它不是一个额外的单独方法。继承方法只有一个副本,而不是两者。它的重载方法是分开的,只是名称相同但签名不同。这就是您在调用任何覆盖方法时获得 Dove 行为的原因。

      2. 这个很简单super,使用它子类可以访问其超类的可访问(可见)实体(实例属性和方法)。如果子类使用super 关键字来调用方法,那么它就是被调用的父类的方法。但是这又可以认为是子类的作者是故意的。一旦编写了类并创建了此类的对象,那么在使用.(点运算符)的对象上,用户只能调用对象中的内容。如果任何方法使用了super 关键字,则它是对象行为的一部分。如果父类方法在子类中被覆盖,子类对象的用户不能调用父类方法的行为。

      3. 最后是的,如果您希望使用Bird(超类)的引用来调用Dove(子类)的任何其他方法,那么您需要将其转换为Dove

      【讨论】:

        猜你喜欢
        • 2014-09-21
        • 2018-11-30
        • 1970-01-01
        • 1970-01-01
        • 2022-11-25
        • 2016-04-20
        • 1970-01-01
        • 1970-01-01
        • 2017-03-17
        相关资源
        最近更新 更多