这是我的代码
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方法?我尝试了这个,但它没有用......
答案 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
而不是扩展它。