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

如果我们队一个类进行继承的时候,我们如果对其内部的逻辑并不十分了解的时候,直接继承的结果就是可能有些方法是类自己内部调用的,而我们在继承这个方法的时候,可能会覆盖某些方法,或者重载某些方法,或者加上了一些自己的逻辑,这样就会吧原来的逻辑和我们自己的逻辑混杂起来,并且如果继承的类内部有使用这个类的话,那么就会调用我们自己写的部分逻辑,那么结果就变得不可预料了

这里的建议是使用包装类模式

package cn.xf.cp.ch02.item16;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set; public class ForwardingSet<E> implements Set<E>
{ /**
* 这个类作为转发类,内部通过复合的方式把set作为一个组件
*/
private final Set<E> s; public ForwardingSet(Set<E> s)
{
this.s = s;
} @Override
public int size()
{
return s.size();
} @Override
public boolean isEmpty()
{
return s.isEmpty();
} @Override
public boolean contains(Object o)
{
return s.contains(o);
} @Override
public Iterator<E> iterator()
{
return s.iterator();
} @Override
public Object[] toArray()
{
return s.toArray();
} @Override
public <T> T[] toArray(T[] a)
{
return s.toArray(a);
} @Override
public boolean add(E e)
{
return s.add(e);
} @Override
public boolean remove(Object o)
{
return s.remove(o);
} @Override
public boolean containsAll(Collection<?> c)
{
return s.containsAll(c);
} @Override
public boolean addAll(Collection<? extends E> c)
{
return s.addAll(c);
} @Override
public boolean retainAll(Collection<?> c)
{
return s.retainAll(c);
} @Override
public boolean removeAll(Collection<?> c)
{
return s.removeAll(c);
} @Override
public void clear()
{
s.clear();
} }

这样,我们在每个方法中调用了私有成员的方法,那么私有成员对外部就是不可见的,它里面的方法就不会和外面的方法混杂起来

package cn.xf.cp.ch02.item16;

import java.util.Collection;
import java.util.Set; /**
*
*功能:包装类
*时间:下午9:58:36
*文件:InstrumentedSet.java
*@author xiaof
*
* @param <E>
*/
public class InstrumentedSet<E> extends ForwardingSet<E>
{
private int addCount = 0; //用来统计set添加了多少元素 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;
} }

【Effective Java】6、使用复合优先于使用继承的更多相关文章

  1. Effective Java 第三版——18. 组合优于继承

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  2. Effective Java 第三版——19. 如果使用继承则设计,并文档说明,否则不该使用

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  3. 【Effective Java】8、优先考虑类型安全的异构容器

    有的时候我们一个容器只有一个类型或几个类型并不能满足我们的要求,比如set中存放的元素类型都是同一种,map也就指定的两种 这里我们可以将键进行参数化,而不是将容器参数化,也就是我们可以给容器传一个键 ...

  4. 【Effective Java】7、优先考虑泛型方法

    package cn.xf.cp.ch02.item27; import java.util.HashSet; import java.util.Set; public class Union { / ...

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

    不要过度设计. 面向对象编程,从一开始被洗脑难免在上手写代码时都会首先思考有没有公共方法啊,能不能把两个类抽象成一个父类再继承啊等,慎重使用继承,当要使用继承时一定要在文档注释中写明重写这个方法会给其 ...

  6. Effective Java 第三版——23. 优先使用类层次而不是标签类

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——29. 优先考虑泛型

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  8. Effective Java 第三版——30. 优先使用泛型方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——33. 优先考虑类型安全的异构容器

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. 使用动态类型dynamic让你的省了很多临时类

    客户端与服务端的数据交互使用的数据格式是json格式,为了使客户端与服务端有类对应关系,进行序列化,所以总要定义一些类,使用动态类型dynamic可以不必要定义那么多类. 测试代码: using Sy ...

  2. sql语句中获取datetime的日期部分或时间部分

    sql语句中获取datetime的日期部分 sql语句中 经常操作操作datetime类型数据.今天在写一个存储过程的时候需要将 一个datetime的值的 日期部分提取出来.网上有许多这方面的介绍. ...

  3. 类的继承和多态性-编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 getLegs(),设置动物名称的方法 setKind(),获得动物名称的方法 getKind(),获得动物数量的方法 getCount()。定义Fish类,是Animal类的子类,

    编写Java应用程序,定义Animal类,此类中有动物的属性:名称 name,腿的数量legs,统计动物的数量 count;方法:设置动物腿数量的方法 void setLegs(),获得腿数量的方法 ...

  4. 浅谈attr()和prop()

    刚开始学JQ的时候 ,看到attr()和prop()这两个属性的时候感觉很迷茫,而且配合官方给出的推荐使用图: prop()可以做到的attr()完全都可以,而且做不到的attr()也可以做到.何用? ...

  5. Uvaoj 11624 - Fire!

    /************************************************************************* > File Name: test.cpp ...

  6. java二维数组的常见初始化

    public class Test{ public static void main(String[] args){ //第一种: //int[][] arr1 = new int[][]{{1,2} ...

  7. Angular从0到1:function(下)

    1.前言 2.function(下) 2.13.angular.isArray(★★) angular.isArray用于判断对象是不是数组,等价于Array.isArray console.log( ...

  8. Angularjs中link函数参数含义小节

    restrictE: 表示该directive仅能以element方式使用,即:<my-dialog></my-dialog>A: 表示该directive仅能以attribu ...

  9. Kruskal算法(三)之 Java详解

    前面分别通过C和C++实现了克鲁斯卡尔,本文介绍克鲁斯卡尔的Java实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的 ...

  10. 邻接矩阵无向图(一)之 C语言详解

    本章介绍邻接矩阵无向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...