里氏替换原则详解--七大面向对象设计原则2

里氏替换原则来源:

我们都知道面向对象有三大特性:封装、继承、多态。所以我们在实际开发过程中,子类在继承父类后,根据多态的特性,可能是图一时方便,经常任意重写父类方法,那么这种方式会大大增加代码出问题的几率。比如下面场景:类C实现了某项功能F1。现在需要对功能修改扩展,将功能扩展为F,其中由原有的功能和新功能F2组成。新功能由类的子类C1来完成,则子类在完成功能的同时,有可能会导致类的原功能发生故障。这时就有人提出了里氏替换原则。里氏替换原则这项原则最早是在1988年,由麻省理工学院一位姓里的女士(Liskov)提出来的。

里氏替换原则定义:

严格的定义:如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都换成o2时,程序P的行为没有变化,那么类型T2是类型T1的子类型。

  通俗的定义:所有引用基类的地方必须能透明地使用其子类的对象。

更通俗的定义:子类可以扩展父类功能,但不能改变父类原有的功能

也就是说,在面向对象设计中,如果用一个基类对象替换一个子类对象,程序不会发生错误,但是软件实体使用用一个子类对象,但是改实体不一定能使用该子类的基类对象,如果使用,程序有可能就会出问题。

例如有两个类,一个类为CLassA,另一个是CLassB类,并且CLassB类是CLassA类的子类,那么一个方法如果可以接受一个CLassA类型的基类对象base的话,如:MethodA(base),那么它必然可以接受一个CLassA类型的子类对象sub,MethodA(sub)能够正常运行。反过来的代换不成立,如一个方法MethodB接受CLassA类型的子类对象sub为参数:MethodB(sub),那么一般而言不可以有MethodB(base),除非是重载方法

例子:沪深A股板块数据请求的里氏替换简析:

在本实例中,可以考虑增加一个新的抽象类StockBlock,而将ShangA和ShenA类作为其子类,数据请求类Quote类针对抽象客户类StockBlock编程,根据里氏代换原则,能够接受基类对象的地方必然能够接受子类对象,因此将Quote中的Request()方法的参数类型改为Code,如果需要增加新类型的客户,只需将其作为String类的子类即可。重构后的结构如图2所示:

里氏替换使用总结:

里氏替换包括以下四层含义:

(1).子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法

(2).子类中可以增加自己特有的方法

(3).当子类的方法重载父类方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。

(4).当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...