Liskov Substitution Principle(LSP): If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behvior of P unchanged when o1 is substituted for o2,then S is subtype of T.
里氏代换原则:如果对于每一个类型为S的对象o1 ,都存在类型为T的对象o2,使得对对所有使用‘T'进行定义的程序P,把其中的o1替换为o2后程序P的行为不发生变化,那么类型S就是类型T的子类型。
里氏替换原则还有一个比较通俗的定义:在所有使用父类型的地方,都应该可以透明的使用子类型;反之则不成立。
里氏替换原则是对面向对象中继承关系的规范。如果一个继承关系不符合里氏替换原则,则必定存在着某种缺陷。
里氏替换原则包含了4个意思:
1.既然子类型可以替换掉父类型,则子类型需要实现父类型的所有方法。如果子类型不能完全实现父类型的方法,或者子类型实现父类型方法有违业务逻辑,则应该考虑用依赖、聚集、组合等关系代替继承。
2.子类型可以有自己的特殊性。子类型在拥有所有父类型的特性后,可以添加自己的特性。但是,实际应用中,多数为用父类型访问父类型或访问访问其子类型。因此,子类型本身的特性可能根本没有访问到的可能性。
3.子类型覆盖或实现父类的方法时输入参数类型可以是父类型方法输入参数类型的父类型。子类型在重写父类型的方法时,其如果参数类型和父类型相同,则是覆写(override);如果参数类型为父类型方法参数类型的父类,则是重载(overload)。如果是重载(overload),子类型的方法可能几乎不可能被调用。如果子类型输入参数类型是父类型参数类型的子类型,那么很可能出错,或者引起业务逻辑混乱。
4.覆写或实现父类的方法时,子类方法的输出结果类型可以是父类型输出结果类型的子类。如果子类方法输出结果为父类方法输出结果的父类型,同样会出错或逻辑混乱。
采用里氏替换原则的目的是增强程序的健壮性,在增加子类时,不影响其他子类的运行。这也是开放封闭原则的要求。
实际应用中,子类多数是被当做父类使用的,因此子类的本身特有而父类没有的特性常常是不可访问的。所以,父类一般是抽象的接口说明,子类只是实现接口而不必添加额外的特性。