前言:Liskov替换原则是关于继承机制的应用原则,是实现开放封闭原则的具体规范,违反了Liskov原则必然意味着违反了开放封闭原则.因此,有必要对面向对象的继承机制及其基本原则做以探索,来进一步了解面向对象中实现抽象,多态技术的基础;继承及其规范
核心思想:
子类必须能够替换其基类.
这一思想体现为对继承机制的约束规范,只有子类能够替换其基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基类.在父类和子类的具体实现中,必须严格把握继承层次中的关系和特征,将基类替换为子类,程序的行为不会发生任何变化.同时,这一约束反过来则是不成立的,子类可以替换基类,但是基类不一定能替换子类.
在面向对象设计中,子类继承于父类,其关系是以IS-A确定的,在.NET语言中以is关键字类判断两个对象的类型是否兼容,例如:Son is Father?Son:null
Liskov替换原则,主要着眼于对抽象和多态建立在继承的基础上,因此只有遵守了Liskov替换原则,才能保证继承复用是可靠的.实现的方法是面向接口编程:将公共部分抽象为基类接口或抽象类,通过Extact Abstract Class,在子类中通过覆写父类方法实现以新的方式支持同样的职责.
注意点:当程序代码中出现了子类与父类:方法调用必须进行显式的类型转换,就表明已经违反了LSP.这也意味着违反了Liskov替换原则就必然违反开放封闭原则,因此这种明显的违规应该被拒绝.开放封闭原则的关键是抽象,体现在基类和子类之间的抽象就是继承,因此LSP原则是实现抽象机制的实施规范,而.NET的虚函数技术能很好解决问题.
规则建议:
⑴Liskov替换原则是关于继承机制的设计原则,违反了Liskov替换原则就必然导致违反开放封闭原则.
⑵ Liskov替换原则能够保证系统具有良好的扩展性,同时实现基于多态的抽象机制,能够减少代码冗余,避免运行期的类别判别.
⑶子类必须满足基类和客户端对其的行为约定,客户端对行为的期望在基类和子类必须保持一致.
⑷IS-A是基于行为方式的,它依赖于客户端的调用方式,对象的行为方式才是值得关注的要素.
⑸子类的异常必须控制在父类可以预计的范围,否则将导致替换违规,违反了Liskov替换原则.
结论:因此,应该面向接口编程,要求父类尽可能使用接口或抽象类来实现,能够保证不违反Liskov替换原则.然而,除了明目张胆的违反LSP原则,有些时候对于LSP的违反是潜在的,从继承层次上并不能了解其问题.必须从客户的角度理解,才能发现子类的行为和客户对父类的期望是不是一致的.因此,按照客户程序的预期来保证子类和父类在行为上的相容,是Liskov替换原则的另一关键.