可继承类必须有文档说明它可覆盖(overridable)的方法的自用性(self-use)。
好的API文档应该描述一个给定的方法做了什么工作,而不是描述它是如何做到的。
类必须通过某种形式提供适当的钩子(hook),以便能够进入到它的内部工作流程中,这种形式可以是精心选择的受保护(protected)方法,也可以受保护的域(比较少见)。
对于为了继承而设计的类,唯一的测试方法就是编写子类。经验表明,3个子类通常足以测试一个可扩展的类。
必须在发布类之前先编写子类进行测试。
为了允许继承,类还必须遵守一些规则。
1.构造器决不能调用可被覆盖的方法。
public class Super { public Super () { overrideMe(); } public void overrideMe(){ } }
public class Sub extends Super { private final Date date; public Sub () { date=new Date(); } @Override public void overrideMe() { System.out.println(date.toString()); } public static void main(String[] args){ Sub sub=new Sub(); sub.overrideMe(); } }上述代码就错误的在构造器中调用了可覆盖方法,而导致NullPointerException。
因为超类构造器会在子类构造器之前运行,所以子类的覆盖方法会在子类构造器之前被运行,这样就导致了上述代码的错误。
为了继承而设计的类如果实现了Cloneable和 Serializable接口会出现特殊的困难。
无论是clone还是readObject,都不可以调用可覆盖的方法,不管是以直接还是间接的方式。
为了继承而设计的类,对这个类会有一些实质性的限制。
但是,对于普通的具体类应该怎么办呢?它们既不是final的,也不是为了子类化设计和编写文档的。
这个问题的最佳解决方案是,对于那些并非为了安全地进行子类化而设计和编写文档的类,要禁止子类化。禁止子类化的方法由两种,类声明为final、所有的构造器私有化或包级私有化,并提供公有的静态工厂方法。
这条建议可能会引来争议,因为很多程序员已经习惯对普通的具体类进行子类化,以便增加新的功能。
如果类是实现了某个接口,那么可以通过包装类的方式来处理。
如果类没有实现具体的接口,禁止继承可能会带来不便。那么需要确保这个类永远不会自己调用自己的任何可覆盖的方法(可覆盖方法永远不会被自用),这样覆盖方法将永远不会影响其他任何方法的行为。