第九章
复用编程
- 源代码层面: 方法,说明等
- 模块层面: 类和接口
- 使用jar和zip包: 将其包括到classpath,使用javap指令获取public方法头
- 继承: 但是需要设计继承结构,有时会引入不想要的方法
- 委托: 在实体之间共享代码和数据的底层机制
- 库层面: API
- 框架层面: 结构层次
- 白盒框架:通过代码层面的继承进行框架扩展
- 黑盒框架:通过实现特定的接口或者委托进行框架扩展
LSP
- 子类型可以增加方法,但不可删
- 子类型需要实现抽象类型(接口、抽象类)中所有未实现的方法
- 子类型中重写的方法必须有相同或子类型的返回值或者符合co-variant的参数
- 子类型中重写的方法必须使用同样类型的参数或者符合contra-variant的参数(此种情况Java目前按照重overload处理)
- 子类型中重写的方法不能抛出额外的 父类 异常
协变,逆变
- 协变
- spec要求越来越强,越来越具体,或本身
- 返回值类型不变或是父类返回值的子类
- 异常只能父类异常的子类或本身
- 逆变
- 参数类型要变得越来越抽象,即父类参数的父类或本身
数组的子类型化
- 数组可以实现类型不同的元素,保存T类型的子类
因为数组元素Number可以接受一个Integer的元素
泛型的子类型化
-
泛型不可以实现对子类型的兼容
因为泛型会使用类型擦除,导致类型List<Integer>
和List<Number>
是不同类型 -
可以使用通配符 ? extends super 来实现泛型的子类型继承,关系如下图所示
-
可以使用& 表示第一个是类继承,之后都是接口实现
委托
- 一个对象请求另一个对象的功能,是一种复用的常见形式
- 如果子类只需要复用父类中的一小部分方法,通过委派机制来实现,避免继承大量无用方法
- 有如下四种委托方式
- Depandency:使用函数参数传入,作为临时变量的使用,类似Comparator
- Association:存在一个字段的委托,该字段只能在构造函数中进行修改
- Composition:存在一个字段的委托,该字段不能被修改
- Aggregation:存在一个字段的委托,该字段能在构造函数、set方法中进行修改
Comparator和Comparable接口
-
Comparator
- 是用于实现元素比较的,元素的接口
- 需要实现compare方法,或者是用lambda表达式进行
public int compara(ElemnetName o1,ElementName o2){ if (o1.value>o2.value) return 1; else if (..==..) return 0; return -1; }
-
Comparable
- 是用于容器排序的接口,就可以实现容器的排序
- 需要实现comparaTo方法,签名如下
public int comparaTo(ElemnetName o){ if (this.value>o.value) return 1; else if (..==..) return 0; return -1; }
CRP原则
- Composite Reuse Principle(CRP):组合优先于继承
接口的组合
黑盒框架和白盒框架
-
白盒框架的原理和实现
- 原理:复用框架代码的结构,在此基础上增加、修改,需要理解框架代码
- 实现:通过继承机制实现
-
黑盒框架的原理和实现
- 原理:复用框架代码的全部,框架代码留出接口以供实现
- 实现:通过委托实现
-
对比