免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 808 | 回复: 0
打印 上一主题 下一主题

构造器内部的多态方法的行为 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-27 08:57 |只看该作者 |倒序浏览

       
       
       
       
       
       
动态邦定调用是在运行的时候决定的,因此无法决定他是属于方法所在的那个类,还是属于那个类的导出类。为了保持一致,大家也许会认为这应该发生在构造器的内部,其实不然,如果要调用构造器内部的一个动态邦定的方法,就要用到那个方法的被覆盖后的定义。然而,产生的效果是相当难以预料的,并且可能造成难以发现的隐藏错误。
构造器的工作实际上就是创建对象。在任何构造器的内部,整个对象可能只是部分形成-----我们只知道基类的对象已经进行初始化,但却不知道哪些类是从我们这里继承而来的。然而一个动态邦定的方法调用却会向外深入到继承层次结构内部,它可以调用导出类的方法。如果在构造器内部这样做,那么就可能会调用某个方法,而这个方法所操作的成员可能还没有被初始化---这样肯定会导致错误。
通过下面的例子我们已可看到错误所在:
               
               
                //: c07:PolyConstructors.java
// From 'Thinking in Java, 2nd ed.' by Bruce Eckel
// www.BruceEckel.com. See copyright notice in CopyRight.txt.
// Constructors and polymorphism
// don't produce what you might expect.
abstract class Glyph {
  abstract void draw();
  Glyph() {
    System.out.println("Glyph() before draw()");
    draw();
    System.out.println("Glyph() after draw()");
  }
}
class RoundGlyph extends Glyph {
  int radius = 1;
  RoundGlyph(int 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中draw()方法是抽象的,这样设计是为了覆盖该方法。在RoundGlyph类中我们覆盖了这个方法,但是Glyph构造器会调用这个方法,结构导致了对RoundGlyph.draw()的调用。但是输出的结构显示当Glyph的构造器调用draw()方法时候,radius不是默认初始值1而是0。该如何解释呢?
我们回到初始化:
1):在其他任何事情发生之前,将分配给对象的储存空间将初始化成二进制的零。
2):如前面所示那样调用基类的构造器,此时调用被覆盖的draw()方法,由于第一步骤地执行,我们回发现radius的初始值变成了0。
3):按照申明的顺序调用成员的初始化。
4):调用导出类的构造器主体。
这样做的一个优点就是将所有的东西都至少初始出成为了0,而不是留作垃圾。如果忘记了对饮用的初始化,纳闷就会在运行的时候出现异常。
因此编写构造器的时候有一条准则:尽可能用简单的方法使对象进入正常状态,如果可以得花,避免调用其他方法。在构造器唯一能能够安全调用的那些方法是基类中的final方法。这些方法不会被覆盖,自然不会出现令我们惊讶的问题了。
------《java编程思想》


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/21684/showart_431201.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP