第6章 继承
一、 继承的语法:
class Thisclass extends Superclass{
//classBody
}
1、 java的所以类都是从Object类继承来得。java的继承是单继承。
2、 子类拥有父类的所有成员和方法,除了private的,除了构造方法。
3、 子类可以覆盖拥有的父类的成员和方法。也可以添加自己的成员和方法。
4、 子类中使用父类被覆盖的成员和方法用super关键字
例:Detergent.java
二、 初始化父类子对象
1. 创建子类的对象时,同时也会创建父类的一个子对象,父类的子对象包含在子类的对象中。
2. 为了保证父类子对象的正确初始化,在子类的构造方法中,Java会首先自动插入对父类默认构建器的调用。
例:Cartoon.Java
3. 如果父类的构造方法含有自变量,则在子类的构造方法必须显式的调用。用super关键字。
例:Chess.java
4. 子类的构造方法必须捕获父类构造方法的所有违例
5. 尽管编译器会强迫我们对基础类进行初始化,并要求我们在构建器最开头做这一工作,但它并不会监视我们是否正确初始化了成员对象。所以对此必须特别加以留意。
三、 确保正确的清除顺序
1. 在确实需要自己去清除一个对象时,必须写一个特别的方法,明确、专门地来做这件事情。
2. 让客户程序员知道他们必须调用这个方法
3. 不管发生什么清除方法必须被执行,必须将这样的清除代码置于一个finally从句中防范任何可能出现的违例事件。
4. 注意清楚顺序与创建顺序相反
例:CADSystem.java
四、 选择合成还是继承
“属于”关系是用继承来表达的,而“包含”关系是用合成来表达的。
五、 上溯造型
1. 子类属于父类的一种类型,可以使用父类对象的地方都可以使用子类的对象,这时子类对象被当作父类对象对待。
2. 继承是对一种特殊关系的表达,意味着“这个新类属于那个旧类的一种类型”。
六、 final关键字
“这个东西不能改变”。之所以要禁止改变,可能是考虑到两方面的因素:设计或效率。
1. final数据:常数
1) 常数的用途:
l 编译期常数,它永远不会改变,必须属于基本数据类型,必须给出一个值。
l 在运行期初始化的一个值,我们不希望它发生变化。对于对象句柄,final句柄一旦初始化,永远不能指向另一个对象。对于基本数据类型的值也同。
例:FinalData.java
2) 空白final
Java 1.1允许我们创建“空白final”。尽管被声明成final,但却未得到一个初始值。空白final都必须在实际使用前得到正确的初始化。
例:BlankFinal.java
3) final自变量
Java 1.1允许我们将自变量设成final属性,方法是在自变量列表中对它们进行适当的声明。这意味着在一个方法的内部,我们不能改变自变量句柄指向的东西。
例:FinalArguments.java
2. final方法
使用final方法的两方面理由:
第一个是为方法“上锁”,防止任何继承类改变它的本来含义。不可被覆盖。
第二个理由是程序执行的效率。关闭动态绑定。
类内所有private方法都自动成为final。
3. final类
不希望从这个类继承。例:Jurassic.java
六、 初始化总结
例:Beetle.java
1、 运行Beetle时(java Beetle),首先装载程序根据Beetle.main到外面找到Beetle.class类。
2、 在装载过程中,装载程序注意它有一个父类Insect,无论是否准备生成Insect的一个对象,都会将Insect.class载入。若Insect也含有父类,则Insect的父类随即也会载入,以此类推。
3、 在根父类(此时是Insect)执行static成员变量初始化,再在下一个子类执行,以此类推。
4、 创建对象。
l 首先,子类中的所有基本数据类型都会设成它们的默认值,而将对象句柄设为null。
l 调用父类构建器:构建器采用与子类构建器完全相同的处理过程;父类的非static成员变量执行规定初始化。创建父类对象。
l 子类的非static成员变量执行规定初始化。
l 最后,执行构建器剩余的主体部分,创建子类对象。