1. 子类型多态:
客户端可用统一的方式处理同类型的对象
2. LSP:
例如:
(1)java编译器的规则(静态类型检查):
a. 子类型可以增加方法,但不可删
b. 子类型需要实现抽象类型中的所有未实现方法
c. 子类型中重写的方法必须有相同或子类型的返回值
d. 子类型中重写的方法必须使用同样类型的参数
e. 子类型中重写的方法不能抛出额外的异常
对于继承而来的指定方法:
-要有更强的不变量
-更弱的前置条件
-更强的后置条件
(2)在编程语言中,LSP依赖于以下限制:
-前置条件不能强化
-后置条件不能弱化
-不变量要保持
-子类型方法参数:逆变
-子类型方法的返回值:协变
-异常类型:协变
a. Covariance(协变):
从父类型到子类型,specific越来越具体,返回值类型越来越具体,异常的类型也是如此。
例如:返回值类型:
异常类型:
b. Contravariance(反协变,逆变)
父类型到子类型:specific越来越具体,然而参数类型要相反地变化,即不变或越来
越抽象(前置条件弱化)。
例如:
c. 更多举例:
数组是协变的:T[]可以包含type T以及T的任何子类:
发生run-time error的原因:
在run-time,java已经知道这个数组实际上被integers的数组实例化。仅仅是引用为
Number[]。
因此,要区分Type of an object vs. Type of a reference
(3)泛型中的LSP。
对于泛型来说:
例如:
ArrayList<String>是List<String>的子类,
List<String>不是List<Object>的子类
类型参数的类型信息在代码编译完成之后是被忽略的,
因此类型信息在run-time并不可得到,这被称为类型擦除(type erasure)。
泛型不是可协变的。
例如:
出现了编译错误。
因此:
(4)泛型中的通配符与LSP。
List<Number>是List<?>的子类型。
List<Number>是List<? extends Object>的子类型
List<Object>是List<? super String>的子类型
在Java.util.collections中:
有静态方法:
来使List<Number>内元素拷入List<Object>
因为此时 List<? super T>是List<? extends T>的一个子类