关于父类构造函数调用子类成员的困惑

问题:
 tij中的习题:  
  class   BaseWithPrint   {  
      public   BaseWithPrint()   {  
      p.println("BaseWithPrint()");  
      print();  
      }  
      public   void   print()   {  
          System.out.println("BaseWithPrint.print");  
      }  
  }  
   
  class   DerivedWithPrint   extends   BaseWithPrint   {  
      int   i   =   47;  
      public   DerivedWithPrint()   {  
      p.println("DerivedWithPrint()");  
      }  
      public   void   print()   {  
          System.out.println("i   =   "   +   i);  
      }  
  }  
   
  public   class   GetFile   {  
   
  public   static   void   main(   String   args[]   ){  
  DerivedWithPrint   dp   =   new   DerivedWithPrint();  
          dp.print();  
  }  
  }  
  输出结果如下:  
  在父类构造函数BaseWithPrint()中调用print(),既然是在父类的构造函数里,那么子类自然还没有构造,其成员函数按说也应该是不存在的呀!可是为什么这时可以调用子类的print()呢?  

回答:
一、运行时刻  
      a   +----+     -+---+-  
          |         |                  
          |         |       A  
          |         |        
      b   +----+     -+-     C  
          |         |          
          |         |       B  
          |         |  
      c   +----+     -+---+-  
   
  我先用这个图表示类及其子类在 内存 中的逻辑概念上的分布。  
  其中:  
  1)   图形中的方框表示类在内存中的存储范围。  
  2)   A表示从a点到b点的内存区  
  3)   B表示从b点到c点的内存区  
  4)   C表示从a点到c点的内存区  
   
  现在有一个类SuperClass及其子类SubClass被加载到内存。其中SuperClass加载于内存区A,那么SubClass占用哪一部分内存呢?  
   
  正确答案是C而不是B。  
   
  二,从代码角度观察  
  对于继承,我们首先应该这样理解,代码中使用继承,只是为了减少代码量(那位,先把砖头放下),而不管父类还是子类,都是相对独立的类。  
   
  当一 个子 类继承自其父类时,从代码角度,就是把其父类的代码重写一遍,然后再加上额外的代码,从而,成其子类。其实,这一 工作 是编译器完成的,当然也不是重写代码,但是我们可以这么直观的理解。  
   
  我按照这种思路改造你的DerivedWithPrint,得到下面的代码:  
   
  //   注意,去掉了extends  
  class   DerivedWithPrint   {  
      int   i   =   47;  
      public   DerivedWithPrint()   {  
   
          //来自BaseWithPrint  
          p.println("BaseWithPrint()");  
          print();  
   
          //   本地  
          p.println("DerivedWithPrint()");  
      }  
   
      public   void   print()   {          
          System.out.println("i   =   "   +   i);  
      }  
  }  
   
  这就是DerivedWithPrint类在运行时刻应该执行的命令及顺序。因为原来的DerivedWithPrint中也有print方法,所以覆盖了其父类的print方法。上述过程好像叫做类的扁平化。  
   
  注意,如果原DerivedWithPrint的print方法中有super.print()字样,那么扁平化之后的print方法应该这样:  
   
      public   void   print()   {  
          System.out.println("BaseWithPrint.print");  
          System.out.println("i   =   "   +   i);  
      }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值