<script type="text/javascript"> 
 </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  • Java继承(inheritance)语法

    


    继承是所有OOP语言(当然包括Java)的组成部分. 当你在创建一个类似.你总是在继承,因为:除非你已明确指出要从其他类继承,否则你就是在隐式的从Java的标准根源类(Object)进行继承.



    组合的语法比较平实,但要实现继承,其语法却要采用截然不同的形式. 在继承过程中, 你需要先声明:"新类和旧类相似"


通常,你首先给类确定一个名称,但在书写类主体的左边花括号之前,应先写下关键字extends,(这里的extend加了s,说明java是充分体现英语规则的,这里是第三人称单数的表现),并在其后写下基类的名称. 看起来像这样:



   

[修饰词] 
subclass 
extends 
baseclass { 

         //.................. 

    }




 当你这么做时,会自动得到基类中的所有数据成员和成员方法.



有几点需要注意:


  1. 在导出类的创建过程中,会首先调用基类的构造方法(逻辑上清晰,因为导出类是在基类的基础上的扩展,所以必须先构造出基类),如果基类继承于另一个基类,那么会继续调用那个基类的构造方法,以此类推.   
  2. 如果基类的构造方法实现了重载(Overloading),那么在导出类的创建过程中是这样的: 默认情况下(没有显式的指定要调用基类的构造方法),则会自动调用没有参数的构造方法.  如果需要制定调用哪个构造方法来构造基类,则应该使用super(参数列表)来调用相应的基类构造方法.
  3. Java是支持多层继承的,B继承了A,C继承B, 那么C具有了A和B的所有方法.




  • 增量开发(Incremental development)

                                                   ___________  Java的继承机制实现了一种设计模式

 


<script type="text/javascript"> 
 </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>


    继承技术的优点之一,就是它支持增量开发模式. 你可以引入新代码而不会在现有代码中引发Bug. 事实上,这种模式可以将新的Bug隔离在新的代码之中.通过从现有的.功能性的类继承并添加数据成员和成员方法(并重新定义现有方法),就可以是别人可能仍在使用的现有代码既不会被改变也不会新增Bug.



    如此一来,类就会被隔离的"很干净". 你甚至不需要为了复用程序代码而调用方法的源代码,而你需要做的仅仅是使用关键字(import)导入一个包即可(这对继承和组合都适用).



   

我们要认识到程序开发是一种增量过程,犹如人类的学习一样,呈现一种循序渐进的姿态,这一点很重要

. 同时可以理解为它是程序代码复用性,模块化的一种表现.  总之是提高了效率! (引用Thinking in java 3rd中的一段描述: "你可以尽你所能的去分析,但当你开始执行一个项目是,你仍然无法知道所有的答案. 如果你将项目视作是一种有机的,进化着的生命体而去培养,而不是打算像盖摩天大楼一样快速见效,你就会获得更多的成功和更迅速的回馈" )  



    虽然就经验而言,继承是一种有用的技术,但在事情已稳定的情况下,你就得采取一个新的视角来审视你的类层次结构,力求将其缩减为一种更实用的结构.

记住, 继承代表着对一种关系的展示,即"次新类是彼旧类的一种类型." 你的程序不应该只关心对比特的处理,而应该通过生成和操作各种类型的对象,用来自问题空间(problem space)中的术语来表现一个模型(model).





继承与初始化



    检查包括继承在内的初始化过程,以对所发生的一切有个全局性的了解,是很有必要的.



       看例子:


1. //! Beetle.java
2. class
3. private int i = 9;
4. protected int
5.     
6. //6 由于Beetle继承于Insect.所以先调用Insect的构造器
7. "i= " + i + ", j= "
8. 39;
9.     }
10.     
11. private static int x1 =     //2 static成员在类被装载是初始化
12. "statci Insect.x1 initialized");
13.         
14. static int print(String s) {  // 10  执行print方法
15.         System.out.println(s);
16. return 47;
17.     }
18. }
19. //1 这里声明继承于incect就会首先装载insect类
20. public class Beetle extends
21. //9 k又去调用了Insect类的print方法
22. private int k = print("Beetle.k initialized"); 
23. public Beetle() {    //7 接着调用Beetle的构造器
24. "k= " + k);  //8 打印k的值
25. "j= " + j);  //11 打印j的值
26.     }
27. //3 接着初始化Beetle类的static成员x2
28. private static int
29. "static Beetle.x2 initialized");
30.     
31. public static void
32. //4 类全部装载完成,开始执行main方法
33. "Beetle constructor"); 
34. //5 创建Beetle对象.开始调用构造器
35. new
36.     }
37. }

   当你键入java Beetle和回车后,所发生的第一件事就是你试图访问Beetle.main()(一个static方法),于是加载器开始启动并找出Beetle类被编译的程序到吗(它被编译到了一个名为Beetle.class的文件之中). 在对它进行加载的过程中,编译器注意到它有一个基类(这是由于extends关键字告知的),于是它首先加载基类.不管你收否打算产生一个该类的对象,这都要放生.(请尝试将对象创建语句注释掉,以证明这一点.)



   如果该基类还有其自身的基类,那么第二个基类就会被加载,如此类推.接下来,根基类中的静态成员初始化(在此例中为Insect)即会被执行,然后是下一个导出类,如此类推. 这种方式很重要,因为导出类的静态初始化可能会依赖于基类成员能否被正确初始化!至此为止,必要的类都已加载完毕,对象就可以被创建了.首先,对象中所有的原始类型都会被设为缺省值,对象引用被设为null ---这是通过将对象内存设为二进制零值而一举生成的.  然后,基类的构造器会被调用.在本例中,他是被自动调用的.但你可以用super来指定对基类构造器的调用(正如在Beetle()构造器的第一步操作.),实例变量(instance variable)按其次序被初始化. 最后,构造器的其余部分被执行.



1 加载类 - 按各个类的继承关系.   (基类先,导出类后)

2 在类的初始化过程中,按照书写的顺序依次初始化类中的static成员(只要是static的,一定会被初始化)

3 开始创建对象,此时对象中的原始类型都被初始化为缺省值,引用为null,紧接着调用基类构造器然后导出类构造器.

4 执行那个public类的main()方法,



                                                 

--------还在不多添加完善中