第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的;把所有的构造器变为私有的,或者包级私有的,并增加一些共有的静态工厂来替代构造器。


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

术语:         对于专门为了继承而设计并且
  • u014723123
  • u014723123
  • 2014年07月01日 11:11
  • 602

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

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

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

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

effective java(17) 之要么为继承而设计,并提供文档说明,要么就禁止继承

effective java 之要么为继承而设计,并提供文档说明,要么就禁止继承 1、 对于专门为了继承而设计并且具有良好文档说明的类而言,该类的文档必须精确地描述覆盖每个方法所带来的影响。 该...
  • dingjianmin
  • dingjianmin
  • 2017年10月18日 21:31
  • 118

《Effective java》读书记录-第17条-要么为继承而设计,并提供文档说明,要么就禁止继承

可继承类必须有文档说明它可覆盖(overridable)的方法的自用性(self-use)。 好的API文档应该描述一个给定的方法做了什么工作,而不是描述它是如何做到的。 类必须通过某种形式提供适当的...
  • sunyx1130
  • sunyx1130
  • 2016年01月13日 12:45
  • 349

在c++中如何阻止类被继承

这个话题是源自于一个面试题,我在网上查了一下有不少这方面的解说!我自己整理了一下,选择了一个自认为是最优方案! 我们从最简单的开始: 首先,大家都知道要阻止类被实例化,可以通过使用private ...
  • yu12345678900
  • yu12345678900
  • 2014年11月22日 17:33
  • 794

java二十三种设计模式------(一)装饰模式 装饰类VS子类继承

Decorator(装饰者模式),顾名思义,就是动态地给一个对象添加一些额外的职责,就好比为房子进行装修一样。        因此,装饰器模式具有如下的特征: 1,它必须具有一个装饰的对象。(就如...
  • qiushi_1990
  • qiushi_1990
  • 2014年08月04日 14:11
  • 1211

C++多重继承与二义性避免

1. 什么是多重继承的二义性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class A{...
  • yang2011079080010
  • yang2011079080010
  • 2016年05月14日 17:34
  • 677

继承与组合有什么区别

组合和继承是面向对象中两种代码复用的方式。组合是指在新类里面创建原有类的对象,重复利用已有类的功能。继承是面向对象的主要特性之一,它允许设计人员根据其它类的实现来定义一个类的实现。 组合和继承都...
  • Harrytsz
  • Harrytsz
  • 2017年03月13日 20:03
  • 551

设计模式(笔记)优先使用对象组合而不是类继承

优先使用对象组合而不是类继承 问 概述 继承和组合都能达到一个代码复用的效果,但是类的继承通常是白箱复用,对象组合通常为黑箱复用。我们在使用继承的时候同时也就拥有了父对象中的保护成员,增...
  • liaoqianchuan00
  • liaoqianchuan00
  • 2014年05月01日 12:00
  • 3415
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:第17条:要么为继承设计,并提供文档说明,要么就禁止继承
举报原因:
原因补充:

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