为什么复合优先于继承?

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)复合优先于继承的更多相关文章

  1. EffectiveJava——复合优先于继承

    继承时实现代码重用的重要手段,但它并非永远是完成这项工作的最佳工具,不恰当的使用会导致程序变得很脆弱,当然,在同一个程序员的控制下,使用继承会变的非常安全.想到了很有名的一句话,你永远不知道你的用户是 ...

  2. Java复合优先于继承

    复合优于继承 继承打破了封装性(子类依赖父类中特定功能的实现细节) 合理的使用继承的情况: 在包内使用 父类专门为继承为设计,并且有很好的文档说明,存在is-a关系 只有当子类真正是父类的子类型时,才 ...

  3. 【Effective Java】6、使用复合优先于使用继承

    这个,不管是什么书都会这样说,因为常常我们并不需要继承,而只是想把类进行一定的扩展,而我们想扩展的属性或方法对应的类都有,这个时候如果两者是is a的关系,这种关系是确实存在的,那么就可以使用继承,不 ...

  4. Java - 复合模式优于继承

    继承是实现代码重用的方法之一,但使用不当则会导致诸多问题. 继承会破坏封装性,对一个具体类进行跨包访问级别的继承很危险. 即,子类依赖父类的实现细节. 如果父类的实现细节发生变化,子类则可能遭到破坏. ...

  5. effective-java学习笔记---优先使用泛型方法30

    泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用. 当你设计新的类型时,确保它们可以在没有这种强制转换的情况下使用. 这通常意味着使类型泛型化. 如果你有任何现有的类型,应该是泛型的但实际 ...

  6. Effecvtive Java Note

    代码应该被重用,而不是被拷贝 同大多数学科一样,学习编程的艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则   创建和销毁对象 1.考虑用静态工厂方法代替构造器. 优势:有名称.不必再每 ...

  7. Effective Java-第4章

    第4章 类和接口 类和接口是Java程序设计语言的核心,它们也是Java语言的基本抽象单元.Java语言提供了许多强大的基本元素,供程序员用来设计类和接口. 13. 使类和成员的可访问性最小化 要区别 ...

  8. 读effection java

    1.考虑用静态工厂方法代替构造器 public static Boolean valueOf(boolean b){ return b?Boolean.TRUE:Boolean.FALSE; } 静态 ...

  9. Chapter 02:复合 VS 继承

    复合优先于继承,继承是实现代码重用的有力手段,并不是所有情况都适用,使用不当会导致软件变得很脆弱.与方法调用不同的是,继承打破了封装性. 总而言之,组合和继承,都能实现对类的扩展.但是要分具体情况用哪 ...

随机推荐

  1. CF10D LCIS (动态规划)

    题目链接 Solution 动态规划. 令 \(f_{i,j}\) 表示 \(a\) 数组前 \(i\) 个和 \(b\) 数组前 \(j\) 所得的最长的 LCIS . 转移很好想: \(a_i!= ...

  2. sql id 或使用nolock

    qlserver 批量插入记录时,对有标识列的字段要设置 set IDENTITY_INSERT 表名 on,然后再执行插入记录操作;插入完毕后恢复为 off 设置 格式:  set IDENTITY ...

  3. 安装ubuntu配置ssh

    vmware安装ubuntu后,必须配置网卡,重新设置MAC,否则无法连接网络(具体方法百度)NAT直连模式xshell连接时host为ifconfig显示的IP地址,不需要设置端口转发,端口还是22 ...

  4. glRotatef 转动方向

    http://blog.sina.com.cn/s/blog_3c6889fe0100qko6.html glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLf ...

  5. 和菜鸟一起学c之gcc编译过程及其常用编译选项【转】

    转自:http://blog.csdn.net/eastmoon502136/article/details/8162626 版权声明:本文为博主东月之神原创文章,未经博主允许不得转载. 上篇文章,知 ...

  6. kvm虚拟机最佳实践系列3-kvm克隆和静态迁移

    KVM克隆和KVM静态迁移 KVM克隆 上一章我们已经有了一个合用的虚拟机镜像,现在我们需要用这个KVM镜像大量的创建和部署 virt-clone就是做这个用的.它简化了我们克隆KVM的步骤. 首先停 ...

  7. linux Centos7 安装Samba服务

    1. 使用Samba服务器需要防火墙开放以下端口 UDP 137 UDP 138 TCP 139 TCP 445 如果碰到 “Unable to save xxxxxxxx 拒绝访问” 的提示,还有最 ...

  8. 新建Maven工程

    这个如果不勾选那个Create a simple project也可以,但是创建完成后还需要修改工程的packaging为pom.还有如果不勾选,就选择maven-archetype-quicksta ...

  9. Hihocoder 1496 寻找最大值(状态压缩 + 高位前缀和)

    题目链接  Hiho 1496 设$f[i]$为二进制集合包含$i$的最大的两个数,这个东西用高维前缀和维护. 高位前缀和转移的具体方案 :枚举每一位,然后枚举每个集合,大的转移到小的. 注意合并的时 ...

  10. CodeChef February Challenge 2018 Broken Clock (三角函数推导 + 矩阵快速幂)

    题目链接  Broken Clock   中文题面链接 令$cos(xα) = f(x)$ 根据三角函数变换公式有 $f(x) = \frac{2d}{l} f(x-1) - f(x-2)$ 我们现在 ...