明辉站/网站教程/内容

Java编程思想读书笔记(6章)

网站教程2024-01-12 阅读
[摘要]第6章 重复运用classes   一.继承(inheritance)    1. 在derived class中overriding某个函数时,只能覆写base class中的接口,即base class中的public或protected或friendly函数。如果试图overriding一个...
第6章 重复运用classes

  一.继承(inheritance)

   1. 在derived class中overriding某个函数时,只能覆写base class中的接口,即base class中的public或protected或friendly函数。如果试图overriding一个private函数,虽然编译通过,但实际上你只是在derived class中添加了一个函数。如

   class Cleanser{
   private void prt(){//(b)

   System.out.println("Cleanser.prt()");
   }
   }
   public class ExplicitStatic extends Cleanser{
   public void prt(){
   System.out.println("ExplicitStatic.prt()");
   }
   public static void main(String[] args){
   Cleanser x = new ExplicitStatic();
   x.prt();//(a)

   }
   }
   因为Cleanser中的prt()是private,所以不能在其derivedclass中被覆写。ExplicitStatic中的prt()只是ExplicitStatic中的一个函数,所以当试图在(a)处通过多态来调用prt()时,会发生错误。如果把(b)处的private去掉,则结果为
   ExplicitStatic.prt()

   2. Super的使用

   1)通过关键字super可以调用当前class的superclass(父类)。

   例6.1.1.1
   class Base{
   Base(){System.out.println("Base()");}
   public void scrub() { System.out.println(" Base.scrub()"); }
   }
   class Cleanser extends Base{
   private String s = new String("Cleanser");
   public void append(String a) { s+=a; }
   public void dilute() { append(" dilute()"); }
   public void apply() { append(" apply()"); }
   public void scrub() { append(" scrub()"); }
   public void print() { System.out.println(s); }
   Cleanser(){
   System.out.println("Cleanser(): " + s);
   }
   public static void testStatic(){
   System.out.println("testStatic()");
   }
   public static void main(String[] args){
   Cleanser x = new Cleanser();
   x.dilute(); x.apply(); x.scrub(); x.print();
   }
   }
   public class ExplicitStatic extends Cleanser{
   ExplicitStatic(){
   System.out.println("ExplicitStatic()");
   }
   public void scrub(){
   append(" Detergen.scrub()");
   super.testStatic();
   super.scrub();//调用的是Cleanser.scrub()

   }
   public void foam() { append(" foam()"); }
   public static void main(String[] args){
   ExplicitStatic x = new ExplicitStatic();
   x.dilute(); x.apply(); x.scrub(); x.foam();
   x.print(); System.out.println("Test base class:");
   Cleanser.main(args);
   testStatic();
   }
   }
   运行结果:

   Base()

   Cleanser(): Cleanser
   ExplicitStatic()

   testStatic()

   Cleanser dilute() apply() Detergen.scrub() scrub() foam()

   Test base class:

   Base()

   Cleanser(): Cleanser
   Cleanser dilute() apply() scrub()

   testStatic()

   2)通过super来调用superclass中的成员时,调用的是最近成员。

   例6.1.1.2
   class Base{
   protected String baseS = "Base";//(a)

   //private String baseS = "Base";
   Base(){System.out.println("Base()");}
   }
   class Cleanser extends Base{
   protected String baseS = "Cleanser";//(b)

   public String s = new String("Cleanser");
   Cleanser(){
   System.out.println("Cleanser(): " + s);
   }
   Cleanser(String a){
   System.out.println("Cleanser(" + a + "): s = " + s );
   }
   }
   public class ExplicitStatic extends Cleanser{
   String s2 = s;
   String baseS = super.baseS; //(c)

   ExplicitStatic(){
   super("ExplicitStatic");
   System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = "
   + baseS + "super.baseS = " + super.baseS);
   baseS = "ExplicitStatic";
   System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
   }
   public static void main(String[] args){
   ExplicitStatic x = new ExplicitStatic();
   }
   }
   结果1:

   Base()

   Cleanser(ExplicitStatic): s = Cleanser
   ExplicitStatic():s2 = Cleanser, baseS = Cleanser,super.baseS = Cleanser
   baseS = ExplicitStatic , super.baseS = Cleanser
   在上面例子中,在三个class中都存在String bases实例。在ExplicitStatic中如果直接调用baseS,则实际调用的是当前类ExplicitStatic中的baseS(即(c)处的成员);如果通过super.bases来调用baseS,则调用的是离当前类ExplicitStatic最近的baseS成员,即Cleanser class中的baseS实例(即(b)处),产生的结果如结果1所示。如果把(b)处语句注释掉,则将调用Base class中的baseS,结果如结果2所示。

   结果2:

   Base()

   Cleanser(ExplicitStatic): s = Cleanser
   ExplicitStatic():s2 = Cleanser, baseS = Base,super.baseS = Base
   baseS = ExplicitStatic , super.baseS = Base
   3. Base class的初始化

   2.1 当你产生derived class对象时,其中会包含base class子对象(subobject)。这个子对象就和你另外产生的base class对象一模一样。

   2.2 通过super()可调用base class的构造函数,但必须放在构造函数的第一行,并且只能在构造函数中运用。

   2.3 初始化顺序为:

   1) 加载代码(.class文件)

   2) 初始化class的静态成员,初始化顺序了“从里到外”,即从baseclass开始。

   3) 在derived class的构造函数中调用base class的构造函数。

   如果在derived class的构造函数中没有通过super()显式调用调用base class的构造函数,编译器会调用bass class的default构造函数并自动生成相应的调用语句,从而产生一个base class实例。如果在derived class的构造函数中通过super()显示调用了父类的构造函数,则调用所指定的构造函数。调用构造函数的调用顺序是“从里到外”。

   4) 调用derived class的构造函数。

   **:当base class没有default构造函数时,必须在derived class的构造函数中通过super显示调用base class的构造函数。

   例:下面代码的初始化过程为:

   1) 装载ExplicitStatic的代码(装载ExplicitStatic.class文件)。

   2) 发现ExplicitStatic有关键字extends,装载ExplicitStatic的baseclass的代码(装载Cleanser.class文件)。

   3) 发现Cleanser有关键字extends,装载Cleanser的baseclass的代码(装载Base.class文件)。

   4) 初始化Base class中的静态成员。

   5) 初始化Cleanser class中的静态成员。

   6) 初始化ExplicitStatic class中的静态成员。

   如果把(c)处的代码注释掉,那么初始化工作到此就结束了。

   7) 为ExplicitStatic对象分配存储空间,并把存储空间初始化为0。

   8) 在ExplicitStatic class的构造中调用super("ExplicitStatic")(在ExplicitStatic class的构造函数中显式调用父类的构造函数),试图产生一个Cleanser class实例。

   9) 为Cleanser对象分配存储空间,并把存储空间初始化为0。

   10) 由于Cleanser class又是继承自Base class,会在Cleanser class的构造函数中通过super()(由于没有显式调用父类的构造函数,所以自动调用父类的default构造函数)调用父类的构造函数,试图产生一个Cleanser class实例。

   11) 产生一个Base class实例。先初始化成员变量,再调用构造函数。

   12) 回到Cleanser class,产生一个实例。首先初始化Cleanser class中的成员数据,再执行构造函数Cleanser(String a)中的其余部分。

……

相关阅读