第17条:要么为继承设计,并提供文档说明,要么就禁止继承

原创 2012年03月21日 22:45:30

首先,该类的文档必须精确地描述覆盖每个方法所带来的影响。换句话说,该类必须有文档说明他可覆盖(overridable)的方法的自用型(self-use)。
对于每个共有的或受保护的方法或构造器,他的文档必须指明该方法或者构造器调用了哪些可覆盖的方法,是以什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的。更一般的,类必须在文档中说明,在哪些情况下会调用可覆盖的方法。(例如:后台的线程或者静态的初始化可能会调用这个方法)
按惯例,如果方法调用了可覆盖的方法,在他的文档注释的末尾应该包含关于这些调用的描述信息。
好的API应该是描述一个给定的方法做了什么工作,而不是描述他是如何做到的。
类必须通过某种形式提供适当的钩子(hook),以便能够进入他的内部工作流程中,这种实行可以精心选择受保护的(protected)方法。
demo:

AbstractList:
    /**
     * Removes from this list all of the elements whose index is between
     * {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
     * Shifts any succeeding elements to the left (reduces their index).
     * This call shortens the ArrayList by {@code (toIndex - fromIndex)}
     * elements.  (If {@code toIndex==fromIndex}, this operation has no
     * effect.)
     *
     * <p>This method is called by the {@code clear} operation on this list
     * and its subLists.  Overriding this method to take advantage of
     * the internals of the list implementation can <i>substantially</i>
     * improve the performance of the {@code clear} operation on this list
     * and its subLists.
     *
     * <p>This implementation gets a list iterator positioned before
     * {@code fromIndex}, and repeatedly calls {@code ListIterator.next}
     * followed by {@code ListIterator.remove} until the entire range has
     * been removed.  <b>Note: if {@code ListIterator.remove} requires linear
     * time, this implementation requires quadratic time.</b>
     *
     * @param fromIndex index of first element to be removed
     * @param toIndex index after last element to be removed
     */
    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }
ArrayList:    
    protected void removeRange(int fromIndex, int toIndex) {
		modCount++;
		int numMoved = size - toIndex;
	    System.arraycopy(elementData, toIndex, elementData, fromIndex,
	                         numMoved);
	
		// Let gc do its work
		int newSize = size - (toIndex-fromIndex);
		while (size != newSize)
		    elementData[--size] = null;
    }    

对于为了继承而设计的类,唯一的测试方法就是编写子类。


构造器决不能调用可覆盖的方法:
超类的构造器在子类的构造器之前运行,所以,子类中覆盖版本的方法将会在子类的构造器运行之前就先被调用。如果该覆盖的版本的方法依赖于子类构造器所执行的任何初始化工作,该方法将不会如预期般的执行。
demo:

package cn.partner4java.test;

public class Super {
	public Super() {
		overrideMe();
	}
	public void overrideMe(){
		
	}
}
package cn.partner4java.test;

import java.util.Date;

public final class Sub extends Super {
	private final Date date;
	public Sub() {
		date = new Date();
	}
	public void overrideMe() {
		System.out.println(date);
	}
	public static void main(String[] args) {
		Sub sub = new Sub();
		sub.overrideMe();
//		后台打印:
//		null
//		Wed Mar 21 22:28:49 CST 2012
	}
}
在为了继承而设计类时,Cloneable和Serializable接口出现了特殊的困难。


为了继承而实现类,对这个类会有一些实质性的限制。


对于那些并非为了安全的进行子类化而设计和编写的文档的类,要禁止子类化。
有两种方法禁止之类化:
把类声明为final的;把所有的构造器变为私有的,或者包级私有的,并增加一些共有的静态工厂来替代构造器。


相关文章推荐

Effective Java 第17条:要么为了继承而设计,并提供文档说明,要么禁止继承

其实在 16 条中说过继承的缺点:  可能会导致子类很脆弱,如果超类用了自用模式并且没有提供相关的文档说明。  后期版本更新中,有可能导致子类实现的方法和超类中同名,从而成...

第17条 类与接口——要么为继承而设计,并提供文档说明,要么就禁止继承

一个专门为了继承而设计并且具有良好文档说明的类,意味着:        1、该类的文档必须精确地描述了改写每一个方法所带来的影响。该类必须有文档说明其可改写的方法的自用性:对于每一个公有的或受保护...

学习effective java-17类和接口之要么为继承而设计,并提供文档说明,要么就禁止继承

该知识点是自己从书籍中学习的笔记。 第16条告诉了我们对一个不是继承而设计并且没有文档的类是很危险的。那么一个为了设计而使用继承并且有很好的文档则应该做以下事情: 该类的文档必须精确地说明每个改写...

8 面向对象(制作帮助文档,通过JDK提供的API学习了Math类,代码块,继承(继承子父成员访问特点,super关键字,方法重写))

面向对象(制作帮助文档,通过JDK提供的API学习了Math类,代码块,继承(继承子父成员访问特点,super关键字,方法重写))...

卡里象棋 C++中国象棋引擎(界面部分用MFC实现)[内含详细设计说明文档](更新于2017-11-16)

中国象棋程序介绍: 辅导过两个本科毕业生的毕业设计,可以自行研究。界面无闪烁。算法使用搜索剪枝算法。使用现代C++实现。数据解构与算法的完好示例。 百度网盘下载...

effective stl 第17条: 使用“swap 技巧”除去多余的容量

#include #include #include #include using namespace std; class people { public: people(); ~peopl...

Effective C++第17条:要在单独的语句中使用智能指针来存储由new创建的对象

第17条: 要在单独的语句中使用智能指针来存储由new创建的对象 假设这里有一个函数用来显示处理优先级,另一个函数根据当前优先级为一个动态分配的 Widget 做一些处理: int prio...

百度官方提供的API详细帮助文档说明

开始学习百度地图API最简单的方式是看一个简单的示例。以下代码创建了一个520x340大小的地图区域并以天安门作为地图的中心:  1. 2. 3. 4. 5. 6. 7. 8. 9....

【cocos2d-js官方文档】十八、Cocos2d-js v3.0的对象构造和类继承

在Cocos2d-JS中,对象的构造方式和Cocos2d-x一样,使用各个类的create函数来构造。在Cocos2d-JS v3.0我们还将为你带来一种传统的方式,即使用new操作符。另外,在v3....

Hibernate学习文档_继承

继承实现的三种策略 1.单表继承    table per class hierarchy,首选数据字典表 Sql,用type字段区分类型 CREATE TABLE `t_animal` (...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第17条:要么为继承设计,并提供文档说明,要么就禁止继承
举报原因:
原因补充:

(最多只允许输入30个字)