对于继承与父类的子类,父类的改动,可能会影响子类的,所以如果要编写可被继承的父类,
父类的文档必须精确的描述改写每一个方法带来的影响。该文档中所说明的自用模式,以及对于其受保护方法和域所隐含的细节,已经做出了永久的承诺。子类在实现时,不管调用父类的方法,还是覆盖父类中的方法,都应该要注意父类实现的细节,而不仅仅是当做普通的API来调用。
为了允许继承,一个类还必须遵守其他的一些约束:构造函数一定不能调用可以被改写的方法,无论是直接还是间接。
如下:
class Super{
public Super(){
m();
}
public void m(){}
}
class Sub extends Super{
private final Date date;
Sub(){
date = new Date();
}
public void m(){
System.out.println(date);
}
}
public class Main {
public static void main(String[] arg){
Sub s = new Sub();
s.m();
}
}
运行结果:
null
Fri Jun 08 08:44:13 CST 2018
因为父类构造函数调用了被改写的方法,而被改写的方法中使用过了date,而父类构造函数是先于子类的,所以两次date是不同的
不仅对于构造函数时这样,对于与构造函数有类似功能的clone和readObject方法,都不能调用一个可改写的方法,无论是直接还是间接。
对于父类实现了Serializable接口,并且该类有一个readResolve或writeReplace方法,那么,必须使这两个方法成为受保护的,而不是私有的。如果是私有的,子类无法继承。
对于未给出说明文档,或者在设计时,未考虑继承的类,应该禁止它被继承。有多个方法禁止一个类被继承:1,final修饰这个类。2,将这个类的构造函数声明为private,利公有的静态工厂来生成实例,等等。