为什么复合优先于继承?

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. vue jsonp解决跨域处理

    1.安装vue jsonp npm i -S vue-jsonp 2.在main.js中导入vue-jsonp import VueJsonp from 'vue-jsonp' 通过use方法,挂载到 ...

  2. HDU 3853 LOOP (概率DP求期望)

    D - LOOPS Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit St ...

  3. [LeetCode] Sqrt(x) 二分搜索

    Implement int sqrt(int x). Compute and return the square root of x. Hide Tags Math Binary Search     ...

  4. Oracle中DBMS_LOB包使用小结

    本文主要介绍oracle数据库中dbms_lob包的使用以及使用dbms_lob包来维护lob数据库类型的基本方法.随着社会的发展,在现代信息系统的开发中,需要存储的已不仅仅是简单的文字信息,同时还包 ...

  5. wget下载整个网站的方法

    转自: http://blog.itpub.net/29867/viewspace-716088/  (修改部分内容) wget --restrict-file-name=ascii -m -c -n ...

  6. studio构建错误Element uses-permission#android.permission.ACCESS_NETWORK_STATE at AndroidManifest.xml:38:5-79 dupli

    今天在项目构建的时候遇到了如下报错: Element uses-permission#android.permission.ACCESS_NETWORK_STATE at AndroidManifes ...

  7. 天猫首页迷思之-jquery实现左侧广告牌图片轮播

    本次要实现的是天猫首页每个楼层左侧的图片轮播效果.见图: 功能点有:点击右箭头向右滑动:点击左箭头向左滑动:什么都不点自动滑动. 1.实现样式.简单分析一下大概的html结构.一个大的div里面包含两 ...

  8. 先刷一波简单的web前端面试题

    1简述一下src与href的区别href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接.src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置 ...

  9. (30)C#Timer类

    有三种Timer 1.System.Windows.Forms.Timer 应用于WinForm中,它的主要缺点是计时不精确,而且必须有消息循环,Console  Application(控制台应用程 ...

  10. 洛谷——P1755 斐波那契的拆分

    P1755 斐波那契的拆分 题目背景 无 题目描述 已知任意一个正整数都可以拆分为若干个斐波纳契数,现在,让你求出n的拆分方法 输入输出格式 输入格式: 一个数t,表示有t组数据 接下来t行,每行一个 ...