7.1 组合语法
toString()方法继承于Object类,当编译器要一个String,而你却只有一个对象时,该方法会自动被调用。System.out.println(dog); Dog类中overrides Object类中的toString()方法。
初始化的四个时间:在定义对象的地方,在类的构造器中,惰性初始化(用的时候判断是否已经初始化,没有的话初始),使用实例初始化。
7.2 继承语法
当创建一个类时,总是在继承。如果没有明确指明从其他类继承,会隐式的从java标准根类Object继承。
class A extends B 继承关键字
每个类可以创建一个main()方法,易于每个类的单元测试 Chess.java中第一行空了,报错。
一个程序中有多个类时,java A执行的是class A中的main(),无论A是public还是包访问权限。
通常情况下,继承父类的数据成员指定为private,所有的方法为public,以便于不在同一个包中的类也可以继承使用父类的方法。
java用super关键字表示超类,当前类时从超类继承来的。
初始化基类,java会自动在导出类的构造器中插入对基类构造器的调用,构造过程从基类向外扩展(最先调用爷爷,再父类,再自己),自动调用仅限于默认构造器。
对于带参数的构造器,需用super显示的调用基类的构造器语句,并且放在导出类构造器的第一句。 Chess(int i){ super(i); }
7.3 代理 delegation
继承和组合的中间方法,将一个成员对象置于所要构造的类中(类似组合),通过这个对象调用所有的方法(类似继承)。
7.4 结合使用组合和继承
java中没有C++析构的概念,(析构函数)对象被销毁时自动调用的函数。由垃圾回收器来完成。但是不能指望垃圾回收器,因为它不一定在何时被调用,也不一定会按照我们想的去执行。如果要清理还需显式的定义一些方法。
在清理时,要注意顺序:防止某个子对象依赖于另一个子对象。一般,执行类的清理动作时,其顺序同生成顺序相反。
name hide:override 重写(覆盖) overload 重载
在导出类中,引入一个新的重载方法是完全可行的,重写父类的函数也是可以的。可以用@Override注解,来防止你在不想重载时意外的重载了。
7.5 在组合和继承之间选择
组合通常用于想在新类中使用现有类的功能而非接口,在新类中嵌入一个对象,通过它实现所需的功能。 一般定义为private,安全;也可以将其对新类的用户公开,可以方便使用。
is-a的关系时用继承,has-a的关系用组合。车子,交通工具(继承)
7.6 protected关键字
protected 就类用户而言是private的(不在同一个包里,非继承,创建对象调用protected的方法),但对于任何继承于此类的导出类或其他任何位于同一个包中的类而言,它是可以访问的。
7.7 向上转型
接收以父类为形参的函数,可以接收其导出类的实参传入,向上转型(继承视为向下的过程)。
向上转型,可能会丢失一些导出类中新定义的方法,但却不会去获取他们,所以不会报错。
继承其实并不太常用,问问自己:是否需要从新类向基类进行向上转型,如果必须向上转型,则继承时必须的。
7.8 final关键字
final :表示无法改变
1. final数据
对于基本类型,表示数值恒定不变;对于对象引用,表示引用恒定不变(不能new指向新对象)。
privatestatic final int VALUE_TWO=39;
//标准书写形式,static final 大写 用下划线分割
staticfinal int INT_5 = rand.nextInt(20);
//final并不表示在编译时可以知道它的值,运行时随机产生值
可以定义空白final,但必须在构造器中初始化:
public finalintj;// 不在构造函数中初始化会报错,也无法在main外部初始化
public static Value v;
publicFinalData(int x){j=x; v= new Value(3);}
final参数:可以读参数,但无法修改参数
void with(finalValue vn,finalinti){
//vn = new Value(8); 不能修改
i++;//错
}
2. final方法
final定义飞方法,在继承中该方法行为保持不变,不能被覆盖(override)。
private方法隐式的指定为final,因为它无法被访问,所以也就无法覆盖了。
但是在导出类中覆盖private方法编译器不会报错。。。因为它本身继承到导出类中是不可见的,再写一个同名称的方法,不算覆盖。如果覆盖private方法把权限改成public或protected 或包访问权限,这时候已经不算是覆盖,而是生成了一个新的方法。
private finalvoidf() {//@Override报错,父类private方法不可见,不算重写
System.out.println("OverridingPrivate.f()");
}
3. final类
表示该类不能被继承 final class Dinosaur{} ,它的方法也就默认没人覆盖了,但它的数据成员可以自定义为final或非final。
final、static final:前者仅表示不可变,后者只有一份不可变(无论new多少个对象,只初始化一次)
7.9 初始化和类加载
java中所有事物都是对象,每个类的编译代码都存在于自己的独立文件之中。该文件只在需要使用程序代码时才会被加载。类的代码在初次使用时,访问static域时,也会被加载。
继承的初始化过程分析。
运行时,如果导出类中有static变量,要先去基类中找static初始化,防止依赖。在所有执行之前(print语句之前)。
然后初始化基类的数据成员,执行基类的构造器;再到导出类的数据成员,导出类的构造器。完成导出类对象的初始化。
程序开发是一个增量的过程,要逐步去扩展,继承和组合是进行的两个工具。