EffectiveJava(17)要么为继承而设计,要么禁止继承
1.如果为了继承而设计类,那么该类必须有文档说明它可覆盖的方法的自用性.对于每个公有的
或受保护的方法或者构造器,它的文档必须指明该方法或者构造器调用了那些可覆盖的方法,是以
什么顺序调用的,每个调用的结果又是如何影响后续的处理过程的
–类必须通过某种形式提供适当的钩子,以便能够进入到它的内部工作流程中,这种形式可以是
精心选择的受保护的方法,也可以是受保护的域
–尽可能的减少暴露的成员
–对于为了继承而设计的类,唯一的测试方法就是编写子类
–构造器绝不能调用可被覆盖的方法,无论直接还是间接:超类的构造器在子类的构造器之前运行,所以
–子类中覆盖版本的方法依赖于子类构造器所执行的任何初始化工作
/**
* 构造器Sub没有机会初始化域date
* @author JacXuan
*
*/
public class Sub extends Super{
private final Date date;
Sub(){
date = new Date();
}
public void ovrrideMe(){
//如果ovrrideMe已经调用了date中的任何方法,当super构造器调用了ovrrideMe
//的时候,调用就会抛出NullPointException方法
System.out.println(date);
}
public static void main(String[] args) {
Sub sub = new Sub();
sub.ovrrideMe();
}
}
public class Super {
public Super(){
//如果ovrrideMe已经调用了date中的任何方法,当super构造器调用了ovrrideMe
//的时候,调用就会抛出NullPointException方法
ovrrideMe();
}
public void ovrrideMe(){
}
}
无论是clone还是readObject,都不可以调用可覆盖的方法:因为二者在行为上非常类似构造器
对于那些并非为了安全地进行子类化而设计和编写文档的类,要禁止子类化
2.程序文档:好的API文档应该描述一个给定的方法做了什么工作,而不是描述它是如何做到的
EffectiveJava(17)要么为继承而设计,要么禁止继承的更多相关文章
- Effective java第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
不要过度设计. 面向对象编程,从一开始被洗脑难免在上手写代码时都会首先思考有没有公共方法啊,能不能把两个类抽象成一个父类再继承啊等,慎重使用继承,当要使用继承时一定要在文档注释中写明重写这个方法会给其 ...
- Effective Java 第三版——19. 如果使用继承则设计,并文档说明,否则不该使用
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- Java:设计类的继承关系时的技巧
继承设计的技巧: (1)将公共操作和域放置在超类 (2)不要使用受保护的域 有些程序员认为,将大多数的实例域定义为protected是一个不错的主意,只有这样,子类才能够在需要的时候直接访问他们.然而 ...
- Python基础(17)_面向对象程序设计(抽象类、继承原理、封装、多态,绑定方法)
一.抽象类 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化 1.在python中实现抽象类 import abc #利用abc模块实现抽象类 class All_file(metacl ...
- Effective C++ 第二版 40)分层 41)继承和模板 42)私有继承
条款40 通过分层来体现"有一个"或"用...来实现" 使某个类的对象成为另一个类的数据成员, 实现将一个类构筑在另一个类之上, 这个过程称为 分层Layeri ...
- C++ Primer 学习笔记_67_面向对象编程 --转换与继承、复制控制与继承
面向对象编程 --转换与继承.复制控制与继承 I.转换与继承 引言: 由于每一个派生类对象都包括一个基类部分,因此能够像使用基类对象一样在派生类对象上执行操作. 对于指针/引用,能够将派生类对象的指针 ...
- C++继承,多重继承,虚继承的构造函数以及析构函数的调用顺序问题
#include <iostream> using namespace std; class A{ int data_a; public: A(){ data_a = ; cout < ...
- python_way day10 python和其他语言的作用域 、 python2.7多继承和3.5多继承的区别 、 socket 和 socketserver源码(支持并发处理socket,多进程,多线程)
python_way day10 1.python的作用域和其他语言的作用域 2.python2.7多继承和3.5多继承的区别 3.socket和socketserver源码(并发处理socket) ...
- javascript实现继承3种方式: 原型继承、借用构造函数继承、组合继承,模拟extends方法继承
javascript中实现继承的三种方式:原型继承.借用构造函数继承.混合继承: /* js当中的继承 js中 构造函数 原型对象 实力对象的关系: 1 构造函数.prototype = 原型对象 2 ...
随机推荐
- code forces 994C
C. Two Squares time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- Python学习笔记(Django篇)——1、环境搭建篇(如何在Pycharm中配置Python和Django)
1.准备好以下东东,并且按照先后顺序进行安装: Python 3.6 (64-bit) Django-1.11.tar.gz pycharm-community-2016.3.2.exe 安装好了 ...
- 7月12号day4总结
今天学习过程和总结 封装JDBC在src/main/java下com.neuedu下utils建立JDBCUilt.java 进行封装,基于框架的开发要么继承父类要么实现接口 一个方法里只能有一个动态 ...
- Numpy基本数据结构
Numpy数组是一个多维数组对象,称为ndarray.其由两部分组成: 1 实际的数据 2 描述这些数据的元数据 一 ndarray的方法 # 多维数组ndarray import numpy as ...
- [LeetCode]Word Search 回溯
Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from l ...
- 数据库函数:sqlite3_exec() SQL语句
函数:sqlite3_exec(),称为便捷函数,封装了好多任务. 函数声明: int sqlite3_exec( sqlite * , const char * sql , sqlite_c ...
- C 语言中char* 和const char*的区别
const char *p = "123"; p[1] = '3'; // 会报错p = "456"; // 不会报错 const char * 只是说指针指向 ...
- shell编程学习笔记【原创】
本文为本人学习笔记,如有转载请注明出处,谢谢 一.Bourne Shell 有如下四种变量: 用户自定义变量 位置变量,即命令行参数 预定义变量 环境变量 二.位置变量 $ 与键入的命令行一样,包含脚 ...
- Linux getcwd()的实现【转】
转自:http://www.cnblogs.com/alan-forever/p/3721908.html 通过getcwd()可以获取当前工作目录. 1 #include <unistd.h& ...
- 使用bottle进行web开发(1):hello world
为什么使用bottle?因为简单,就一个py文件,和其他模块没有依赖,3000多行代码. http://www.bottlepy.org/docs/dev/ 既然开始学习,就安装它吧. pip3 in ...