1. 里氏替换原则(Liskov Substiution Principl,LSP)
如果要说里氏替换原则,就必须说继承,因为里氏替换原则就是继承的缺点的解决方案。
继承好处
l 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性。
l 提高代码的重用性
l 提高代码的可扩展性,很多开源框架的扩展接口都是通过继承父类完成的。
l 提高产品或醒目的开放性
继承缺点
l 降低代码的灵活性。子类必须拥有父类的属性和方法,让子类自由的世界中有了很多约束
l 增强耦合性。当父类的常量、变量和方法发生更改时,就要考虑子类的修改。而这修改没有在规范的环境下,这就是很大片的重构。
什么是里氏替换原则呢:有两种定义
l 最正宗的定义: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 behavior of P is unchanged when O1 is substituted for O2 then S is a subtype of T.(如果对每一个类型S的对象O1,都有类型为T的对象O2,使得以T定义的所有程序P在所有的对象O1都替换成O2,程序P的行为没有发生变化,那么类型S是类型T的子类型。)
l 第二种定义:最清晰明确的。Function that use pointers or references to vase classes must be able to use object if derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象。)
只要父类能出现的地方子类就可以出现,而且替换为子类也不会产生任何错误或异常。但是有子类的地方,父类未必就能适应。就是有子类出现的地方父类未必就可以出现。(子类范围面积比父类大。)
里氏替换原则并不少见,经常定义一个接口或抽象类,然后编码实现,调用类则直接传入接口或抽象类,其实这里已经使用了里氏替换原则。
里氏替换原则也要求制定一个契约,就是父类或接口,这种设计方法叫做Design by Contract(契约设计)跟里氏替换原则有着异曲同工之妙。
会出现父类存在的地方,子类就未必可以存在,因为一旦把子类作为参数传入,调用者就很可能进入到子类方法范畴。
子类中方法的前置条件必须与超类中被覆写的方法前置条件相同或者更宽松。
里氏替换原则的目的就是增强程序的健壮性,版本升级时也可以保持非常好的兼容性。即使增加子类,原有的子类还可以继续运行。
注意
l 在类中调用其他类务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则。
l 如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”。则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承。
l 在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和。
原文链接:https://www.f2er.com/javaschema/286781.html