返回首页

构造器内部的多态方法

时间:2009-06-10 22:41来源:未知 作者:admin 点击:
package net.thinking.in.java.fourth; class Glyph{ void draw(){ System.out.println(Glyph.draw()); } public Glyph() { // TODO Auto-generated constructor stub System.out.println(Glyph() before draw()); draw(); System.out.println(Glyph() after draw()); } } cl
  

package net.thinking.in.java.fourth;

class Glyph{
    void draw(){ System.out.println("Glyph.draw()"); }
    public Glyph() {
        // TODO Auto-generated constructor stub
        System.out.println("Glyph() before draw()");
        draw();
        System.out.println("Glyph() after draw()");
    }
}

class RoundGlyph extends Glyph{
    private int radius = 1;
    public RoundGlyph(int r) {
        // TODO Auto-generated constructor stub
        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.draw()方法设计为将要被覆盖,这种覆盖是在RoundGlyph中发生。但是Glyph构造器会调用这个方法,结果导致对 RoundGlyph.draw()的调用,这看起来似乎是我们的目的。但是如果看到输出结果,我们会发现当Glyph的构造器调用draw()方法 时,radius不是默认初始值1,而是0。

原因:初始化实际过程
1. 在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。
2. 调用基类构造器。此时,调用被覆盖后的draw()方法(要在调用RoundGlyph构造器之前调用),由于步骤1的缘故,我们此时会发现radius的值为0。
3. 按照生命的顺序调用成员的初始化方法。
4. 调用导出类的构造器主体。

解决方案:编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。在构造器内唯一能够安全调用的那 些方法是基类中的final方法(也适用于private方法,他们自动属于final方法)。这些方法不能被覆盖,因此也就不会出现上述令人惊讶的问 题。你可能无法总是能够遵循这条准则,但是应该朝着它努力。

顶一下
(1)
25%
踩一下
(3)
75%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
小朱 查看详细资料 发送留言 加为好友 用户等级:超级会员 注册时间:2008-11-18 17:11 最后登录:2013-12-24 23:12
推荐内容