1.行为子类型和LSP原则
子类型多态:客户端可用统一的方式处理不同类型的对象
子类型多态要遵守的原则:
方法中的LSP原则:更强的不变量、更弱的前置条件、更强的后置条件
**例:看下列子类是否满足LSP原则
父类:
子类:
(解:子类具有和父类一样的表示不变量,并且有额外的表示不变量,表示不变量没有变弱;并且重写的方法有相同的前置和后置条件,满足LSP)
**例:看下列子类是否满足LSP原则
次父类:
子类:
(解:次父类的)**********************
2.LSP是一种对子类型关系的特殊的定义,被称为 强行为子类化
要求:
1. 协变Covariance
父类型-->子类型:越来越具体specific
返回值类型:不变或变得更具体
异常的类型:也是如此。
例:
2. 反协变、逆变Contravariance
父类型-->子类型:越来越具体specific
参数类型:要相反的变化,要不变或越来越抽象
例:
3.总结协变与逆变
(1.子类型(属性、方法)关系;2.不变性,重写方法;3.协变,方法返回值变具体;4.逆变,方法参数变抽象;5.协变,参数变的更具体,协变不安全)
1.数组中协变(数组是协变的)
(在java的子类型规则中,一个T类型的数组,其中包含的元素可以是T类型也可以是T的子类型)
2.泛型中的LSP
(注意:第一行符合子类型关系,而第二行不符合子类型关系)
(原因:因为在泛型中存在 类型擦出(type erasure))
(所以,泛型不是协变)
例:???????????????
尽管Integer是Number的子类型,但Box
3.为了解决类型擦除的问题-----Wildcards(通配符)
(?是一种不确定的类型)
1.更低边界的通配符:
2.更高边界的通配符:
3.带有通配符的泛型的LSP:
1.委派:一个对象请求另一个对象的功能(“委托”发生在objet层面,而“继承”发生在class层面)
*例:继承与委派的对比
委派的类型:
模型:
①Use--临时性的delegation
例:
(直接在方法中委托其他类的对象,只是使用的其他类的对象,是临时的)
②Association--永久性的delegation
例:
(一个类有其他类的对象声明(has),是永久性的)
③Composition--更强的delegation
例:
(一个类有另一个类的对象声明(is part of),更是永久性的)
④Aggregation
例:
2.委派使用的情况
CRP原则:Composite Reuse Principle
**例:一个公司要分红,但公司不同职位(经理、程序员、秘书)的分红不同(用继承和组合机制对比实现)
继承:
父类:
子类:
(但不同的人分红不同,所以每种职位都要重写父类中的方法,代码很赘余)
(核心问题:每个Employee对象的奖金计算方法都不同,在object层面而非class层面。)
组合:(CRP)
更为一般的委派的设计:
**例:对比继承和 组合
继承:
组合:
1.
2.