Java覆盖解释

时间:2009-08-31 11:46:07

标签: java inheritance override

这是我的代码

class Glyph { 
  void draw() { System.out.println("Glyph.draw()"); } 
  Glyph(int i) { 
    System.out.println("Glyph() before draw()"); 
    draw(); 
    System.out.println("Glyph() after draw()"); 
  } 
}  

class RoundGlyph extends Glyph { 
  private int radius = 1; 
  RoundGlyph(int r) { 
      super(r);
    radius = r; 
    System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius); 
  } 
  void draw() { 
      System.out.println("RoundGlyph.draw(), radius = " + radius); 
  } 
}  

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

输出:

Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5

为什么超类Glyph的构造函数调用子类RoundGlyph的draw方法?如何从超类的构造函数中调用超类的draw方法?我尝试了这个,但它没有用......

5 个答案:

答案 0 :(得分:3)

从ctors调用非私有或非静态方法是不好的做法,因为从ctor调用非私有或非静态方法将导致在子类型中调用方法,就像在你的情况下一样。 所以,不要这样做并改变你的应用程序的设计。

答案 1 :(得分:3)

  

为什么超级调用的构造函数绘制子类的方法

这是方法重写的方式。如果子类已经实现了与其父(或祖父母等)具有相同签名的方法,则当其中一个祖先调用该方法而未指定super.时,将调用sublcass的版本。

  

我将如何从超级构造函数中调用super方法

没有办法指定调用方法的 my 版本,而不是子类的版本。

请注意,除了设置类所需的构造函数之外,您不应该在构造函数中进行任何工作。

答案 2 :(得分:2)

我同意这个问题的答案是构造函数的糟糕设计。但是如果需要从基类内部调用基类方法,则需要将代码提取到未重写的方法中。实例化的子类对象将始终执行重写的方法。

class Glyph {
    void draw() {
        doDraw();
    }

    private void doDraw() {
        System.out.println("Glyph.draw()");
    }

    Glyph(int i) {
        System.out.println("Glyph() before draw()");
        doDraw();
        System.out.println("Glyph() after draw()");
    }
}

答案 3 :(得分:1)

你做不到。所有方法在Java中都是虚拟的,您无法指定要在继承层次结构中执行哪些方法。唯一的例外是子类可以调用其父类的方法,即使它们自己覆盖它。

如果您不希望方法可以覆盖,请将其声明为final(或私有)。

答案 4 :(得分:1)

基类构造函数正在调用子类draw()方法,因为您正在创建子类类型的对象。这就是它应该如何工作。子类的方法由类加载器加载,而不是在构造函数被调用时加载,因此它们已经可以由构造函数执行。有关详细信息,请参阅the relevant section of the JLS

您不能以您尝试的方式从子类的实例调用基类draw()方法。您需要 not 覆盖子类中的方法,或者将您的设计更改为封装Glyph而不是扩展它。