里氏替换
里氏替换原则 Liskov Substitution Principle,LSP
Inheritance should ensure that any property proved about supertype objects also holds for subtype objects
继承必须确保超类所拥有的性质在子类中仍然成立。
里氏替换原则,主要在阐述关于继承的一些原则。什么时候使用继承,什么时候不应该使用继承。主要反映基类和子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
通过以下Demo来分析,继承时应该避免出现的问题:
class Bird {
private flyTime: number;
constructor(flyTime:number){
this.flyTime = flyTime;
}
getFlyTime(){
console.log(`鸟的飞行时间:${this.flyTime}`);
}
}
class Ostrich extends Bird {
constructor(fltTime:number){
super(fltTime)
}
getFlyTime(){
console.log(`鸵鸟不会飞`);
}
}
(()=>{
const ostrich = new Ostrich(12);
ostrich.getFlyTime();
})();
AI 代码解读
以上程序是没有问题,但在设计上有问题:Ostrich类继承了Bird类,同时也重写了getFlyTime方法,改变了父类使用该方法是为了计算飞行时间的,这样的调用存在着风险,违反了里氏替换原则。因为里氏替换原则是实现开闭原则的重要方式之一,所以修改了父类的方法,是没有进行扩展,而是进行修改的操作。
解决方案是,去掉他们之间的继承关系。可以新建一个基类,增加计算飞行时间方法和输出特性方法,Bird和Ostrich类分别继承新的基类,实现各自的功能。
如何正确使用继承
- 子类可以扩展父类的功能,但尽量不改变父类原有的功能
- 子类的方法实现父类的方法时,条件可以增强但是功能应该是对等的,
- 子类可以增加自己特有的方法
里氏替换原则作用
- 它避免了因继承父类造成可复用性降低的缺点
- 它是动作正确性保证,即父类要实现的功能还是保持一致,避免引入新的错误。
- 加强程序的健壮性,同时变更时可以做到非常好的兼容性
参考资料