为什么父构造函数内的方法实际调用子方法

时间:2015-09-04 05:28:49

标签: java methods constructor polymorphism

 class Glyph {
      void draw() {
        System.out.println("glyph.draw()");
      }

    Glyph() {
        System.out.println("glyph() before draw");
        draw();
        System.out.println("glyph() after draw");
    }
 }

 class RoundGlyph extends Glyph {
    private int radius = 1;

    RoundGlyph(int r) {
        radius = r;
        System.out.println("roundGlyph.RoundGlyph:" + radius);
    }

    @Override
    void draw() {
        System.out.println("roundGlyph.draw:" + radius);
    }
}

public class PolyConstructors {
    public static void main(String[] args) {
      new RoundGlyph(3);
    } 
}

输出是:

glyph() before draw
**roundGlyph.draw:0**
glyph() after draw
roundGlyph.RoundGlyph:3

我对第二个结果感到困惑,为什么父类构造函数中的代码draw()实际上调用了除父绘制方法之外的子绘制方法?

3 个答案:

答案 0 :(得分:2)

因此draw()调用正在调用this.draw(),其中this是您的实例化对象。

在这种情况下,this指的是RoundGlyph类型的对象,它覆盖了Draw()方法。在RoundGlyph对象的上下文中,没有Draw方法可以打印"glyph.draw()"已经消失的方法。

答案 1 :(得分:2)

这是因为重写。

什么是压倒一切?

  

在面向对象编程中,方法重写是一种语言功能,它允许子类或子类提供已由其某个超类或父类提供的方法的特定实现。子类中的实现通过提供与父类中的方法具有相同名称,相同参数或签名以及相同返回类型的方法来覆盖(替换)超类中的实现。

如何决定执行哪种方法?

  

执行方法的版本将由用于调用它的对象确定。

请注意,对象决定调用哪个方法。

在您的情况下,在调用RoundGlyph时使用draw()的对象。由于班级RoundGlyph会覆盖draw函数,因此会调用draw内的RoundGlyph

如需进一步阅读,请参阅thisthis

答案 2 :(得分:1)

每当你创建子类的对象时,调用父调用的默认构造函数然后是子类构造函数。方法调用在运行时确定,它取决于正在创建的对象。

如果您创建Glyphnew Glyph())的对象,则会调用其Glyph.draw()方法。如果您创建RoundGlyph对象,则会调用其RoundGlyph.draw()方法。

如果要从子类重写方法调用父类方法,则必须从子类方法显式调用(使用super关键字)。

@Override
void draw() {
    super.draw();
    System.out.println("roundGlyph.draw:" + radius);
}

有关更详细的说明和示例,请参阅inheritance documentation