为什么这个对象可以访问它的父类的方法?

时间:2017-04-26 13:59:08

标签: java inheritance polymorphism superclass

这个问题来自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()打印的内容是什么?

我认为答案是"飞唧唧",但是教科书说答案是"飞唧唧唧唧"。我认为那羽鸽子'只能访问Bird中可用的方法?我的印象是,如果用户想要访问Dove中的方法,那么鸽子就可以了。必须投向鸽子。

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

4 个答案:

答案 0 :(得分:4)

简而言之,当您访问act的{​​{1}}方法时,会调用pigeon的覆盖。

  

我认为那羽鸽子'只能访问Bird中可用的方法吗?

至少,对于没有应用强制转换的情况,这是肯定的。但是,方法Dove可用于act类,即静态已知的Bird类型,因此调用编译正常。

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

  

Bird会给出相同的输出吗?

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

答案 1 :(得分:2)

您在这里遇到的是多态。而不是直接回答你的各种问题;我将简单解释你正在观察的案例。

你在Dove的一个实例上调用act();这导致超级电话;印刷"飞"。

那个超级方法然后调用makeNoise() ... on"本身"。但正如所说:"本身"是一个鸽子对象;因此你得到了鸽子的声音! " COO"!

然后Dove实施结束;并打印" waddle"。

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

以上为您提供了所有您自己回答其他问题所需的信息。在这个意义上:不要求答案;请求解释;并使用这些来解决这个难题!

答案 2 :(得分:2)

  • 班级Dove执行覆盖act的方法makeNoiseBird。覆盖意味着将方法可见的行为更改为子类(在您的情况下为Dove)。如果子类具有publicprotected访问修饰符,或者如果它们具有package private访问修饰符且子类属于与超级相同的包,则子类可见方法 - 类。
  • pigeonDove
  • 的一个实例
  • 调用pigeon.act()会调用Dove.act
  • Dove.act调用super.act Bird.act
  • Bird.act打印fly并致电makeNoise pigeon,致电Dove.makeNoise
  • Dove.makeNoise调用super.makeNoise Bird.makeNoise
  • Bird.makeNoise打印chirp
  • Dove.makeNoise在致电coo
  • 后打印super.makeNoice

答案 3 :(得分:1)

从你的问题“我认为'鸽子'只能访问Bird中可用的方法?我的印象是,如果用户想要访问Dove中的方法,'鸽子'就必须投向Dove。”这实际上是 true

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

  1. 当我们的代码Bird pigeon = new Dove(); Dove扩展Bird时,我们的实际对象为Dove,引用类型为Bird。由于对象属于Dove所以它具有方法,来自超类的继承以及添加的方法。

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

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

  4. 最后是的,如果您希望使用Dove(超类)的引用调用Bird(Sub class)的任何其他方法,则需要将其强制转换为{{1} }。