为什么此对象可以访问其父对象 class 的方法?

Why can this object access methods of it's parent class?

此题取自 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 之外的 class 中:

Bird pigeon = new Dove(); 

调用 pigeon.act() 的结果打印了什么?

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

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

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

I thought that 'pigeon' could only access methods available in Bird?

这当然是正确的,至少在没有应用转换的情况下是这样。但是,方法 act 在 class Bird 上可用,pigeon 的静态已知类型,因此调用编译正常。

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

Would Bird pigeon = new Bird(); give the same output?

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

您在这里体验到的是多态性的实际应用。而不是直接回答你的各种问题;我就简单说明一下你观察到的情况。

您在 Dove 实例上调用 act();这会导致调用 super;打印 "fly".

该超级方法随后调用 makeNoise() ... "itself"。但如前所述: "itself" 是一个 Dove 对象;因此你得到了鸽子的噪音! "coo"!

那么Dove实现结束;并打印 "waddle".

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

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

  • class Dove 覆盖 class [=13] 的 actmakeNoise 方法=].覆盖意味着将方法 visible 的行为更改为子 class(在您的情况下为 Dove)。如果方法具有 publicprotected 访问修饰符,或者如果它们具有 package private 访问修饰符且子 class 方法对子 class 可见与 super-class 属于同一个包。
  • 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

根据你的问题"I thought that 'pigeon' could only access methods available in Bird? I was under the impression that, if the user wanted to access methods in Dove, 'pigeon' would have to be cast to Dove."这实际上是正确

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

  1. 当我们有像 Bird pigeon = new Dove(); 这样的代码时,其中 Dove 扩展 Bird 我们有 Dove 的实际对象并且引用类型是 Bird.由于对象是 Dove 的,因此它具有方法,继承 来自 super class 以及 added

  2. 另外一个重点是所有的overriden方法只有一个实例。它的 Overriden 意味着同一方法的行为已被修改,它不是一个额外的单独方法。只有一个继承方法的副本,而不是两个。它的重载方法是分开的,只是名称相同但签名不同。这就是当您调用任何重写方法时获得 Dove 行为的原因。

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

  4. 中被覆盖
  5. 如果您希望使用 Bird(超级 class 的引用调用 Dove(子 class)的任何其他方法) 那么您需要将其转换为 Dove