EffectiveJava(16)复合优先于继承
为什么复合优先于继承?
1.继承违反了封装原则,打破了封装性
2.继承会不必要的暴露API细节,称为隐患.比如通过直接访问底层使p.getProperty(K,V)的键值对可以不是String类型
3.继承限定了类的性能,它会把它的缺陷传递给子类
1.复合:不必扩展现有的Set类,而是在此类中加一个私有域,它引用现有类的一个实例
2.它的封装特性使得它更加健壮灵活
3.复合允许设计新的API隐藏父类的缺点
在继承中的例子
public class InstrumentedHashSet<E> extends HashSet<E> {
//The number of attempted element insertions
//试图插入元素的数量
private int addCount = 0;
public InstrumentedHashSet(){
}
public InstrumentedHashSet(int initCap,float loadFactor){
super(initCap,loadFactor);
}
@Override
public boolean add(E e){
addCount++;
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends E> c){
addCount+=c.size();
return super.addAll(c);
}
public int getAddCount(){
return addCount;
}
}
mian方法
InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
s.addAll(Arrays.asList("Snap","Crackle","Pop"));
//返回的值为6
//在hashSet内部 addAll方法是基于add实现的,
System.out.println(s.getAddCount());
使用复合改良这个例子
/**
* 新类
* 转发:新类中的每个实例方法都可以调用被包含的现有类实例中对应的方法并返回结果
* @author JacXuan
*
* @param <E>
*/
public class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
public ForwardingSet(Set<E> s) {
this.s = s;
}
....
/**
* 复合:不必扩展现有的Set类,而是在此类中加一个私有域,它引用现有类的一个实例
* @author JacXuan
*
* @param <E>
*/
public class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount =0;
//引用ForwardingSet实例
public InstrumentedSet(Set<E> s) {
super(s);
}
@Override
public boolean add(E e){
addCount++;
return super.add(e);
}
@Override
public boolean addAll(Collection<? extends E> c){
addCount+=c.size();
return super.addAll(c);
}
public int getAddCount(){
return addCount;
}
//将此类用于临时替换一个原本没有技术特性的Set实例
//不给出具体Dog类代码
// static void walk(Set<Dog> dogs){
// InstrumentedSet<Dog> iDogs = new InstrumentedSet<Dog>(capacity);
// }
}
//此包中的包装类可以被用来包装任何set实现,并且可以结合任何先前存在的构造器一起工作
//Set<Date> s = new InstrumentedSet<Date>(new TreeSet<Date>(cmp));
//Set<E> s2 = new InstrumentedSet<E>(new HashSet<E>(capacity));
同样,继承也有使得功能复杂的类传播性更好,那么我们该何时使用继承呢
当子类真正是超类的子类型的时候,可以使用继承
EffectiveJava(16)复合优先于继承的更多相关文章
- EffectiveJava——复合优先于继承
继承时实现代码重用的重要手段,但它并非永远是完成这项工作的最佳工具,不恰当的使用会导致程序变得很脆弱,当然,在同一个程序员的控制下,使用继承会变的非常安全.想到了很有名的一句话,你永远不知道你的用户是 ...
- Java复合优先于继承
复合优于继承 继承打破了封装性(子类依赖父类中特定功能的实现细节) 合理的使用继承的情况: 在包内使用 父类专门为继承为设计,并且有很好的文档说明,存在is-a关系 只有当子类真正是父类的子类型时,才 ...
- 【Effective Java】6、使用复合优先于使用继承
这个,不管是什么书都会这样说,因为常常我们并不需要继承,而只是想把类进行一定的扩展,而我们想扩展的属性或方法对应的类都有,这个时候如果两者是is a的关系,这种关系是确实存在的,那么就可以使用继承,不 ...
- Java - 复合模式优于继承
继承是实现代码重用的方法之一,但使用不当则会导致诸多问题. 继承会破坏封装性,对一个具体类进行跨包访问级别的继承很危险. 即,子类依赖父类的实现细节. 如果父类的实现细节发生变化,子类则可能遭到破坏. ...
- effective-java学习笔记---优先使用泛型方法30
泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用. 当你设计新的类型时,确保它们可以在没有这种强制转换的情况下使用. 这通常意味着使类型泛型化. 如果你有任何现有的类型,应该是泛型的但实际 ...
- Effecvtive Java Note
代码应该被重用,而不是被拷贝 同大多数学科一样,学习编程的艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则 创建和销毁对象 1.考虑用静态工厂方法代替构造器. 优势:有名称.不必再每 ...
- Effective Java-第4章
第4章 类和接口 类和接口是Java程序设计语言的核心,它们也是Java语言的基本抽象单元.Java语言提供了许多强大的基本元素,供程序员用来设计类和接口. 13. 使类和成员的可访问性最小化 要区别 ...
- 读effection java
1.考虑用静态工厂方法代替构造器 public static Boolean valueOf(boolean b){ return b?Boolean.TRUE:Boolean.FALSE; } 静态 ...
- Chapter 02:复合 VS 继承
复合优先于继承,继承是实现代码重用的有力手段,并不是所有情况都适用,使用不当会导致软件变得很脆弱.与方法调用不同的是,继承打破了封装性. 总而言之,组合和继承,都能实现对类的扩展.但是要分具体情况用哪 ...
随机推荐
- 【Android开发日记】之入门篇(十)——Android应用配置文件解析
在Android基于组件的应用设计架构中,配置文件是一个很重要的元素.它将应用所包含的组件.各组件的能力和配置以及应用环境介绍给Android框架层的各个服务,让Android知道如何去调度应用中的各 ...
- HDU1892 See you~
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission( ...
- keystone总结
1. Keystone(OpenStack Identity Service)是OpenStack框架中,负责身份验证.服务规则和服务令牌的功能, 它实现了OpenStack的Identity API ...
- UVA 10519 !! Really Strange !!
//ans=2*n+(n-1)(n-2) n>=2#include <map> #include <set> #include <list> #include ...
- 12.OpenStack镜像和存储服务配置
配置镜像服务 编辑 /etc/glance/glance-api.conf与/etc/glance/glance-registry.conf添加以下内容 [DEFAULT] notification_ ...
- 字符编码笔记:ASCII、Unicode、UTF-8 和 Base64
1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态(-128~127),这被称为一 ...
- python接口自动化1-发送get请求【转载】
本篇转自博客:上海-悠悠 原文地址:http://www.cnblogs.com/yoyoketang/tag/python%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E ...
- ros结合catkin_make和qtcreator
首先是ros官网关于IDE的教程: http://wiki.ros.org/IDEs#QtCreator 1.qtcreator安装 从官网上下载.run文件, https://info.qt.io/ ...
- VirtualBox安装部署的Ubuntu16.04的步骤
1.下载ubuntu16.04镜像 http://cn.ubuntu.com/download/ 以及虚拟机软件VirtualBox https://www.virtualbox.org/wiki/D ...
- AC日记——Two poj 1849
Two 思路: 树形DP求直径: 答案是边权总和*2-直径: dp[i][1]::以i为根的子树中最长的路径: dp[i][0]::以i为根的子树中次长的路径: 来,上代码: #include < ...