一、概念
里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象
里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物
实现方法
里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法(除非基类中的纯虚函数必须要重写,虚函数可以重写,普通函数不能或者尽量不要重写)
子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
子类中可以增加自己特有的方法
当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松
当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等
我们在运用里氏代换原则时,尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。里氏代换原则是开闭原则的具体实现手段之一
二、例程
在对系统进行进一步分析后发现,无论是普通客户还是VIP客户,发送邮件的过程都是相同的,也就是说两个send()方法中的代码重复,而且在本系统中还将增加新类型的客户。为了让系统具有更好的扩展性,同时减少代码重复,使用里氏代换原则对其进行重构。
在本实例中,可以考虑增加一个新的抽象客户类Customer,而将CommonCustomer和VIPCustomer类作为其子类,邮件发送类EmailSender类针对抽象客户类Customer编程,根据里氏代换原则,能够接受基类对象的地方必然能够接受子类对象,因此将EmailSender中的send()方法的参数类型改为Customer,如果需要增加新类型的客户,只需将其作为Customer类的子类即可。重构后的结构如图2所示:
三、代码示例
正确的做法是:取消几维鸟原来的继承关系,定义鸟和几维鸟的更一般的父类,如动物类,它们都有呼吸的能力,鸟类继承自动物类,燕子继承自鸟类;几维鸟继承自动物类。
#include <iostream>
class Animal{
public:
float runSpeed;
virtual void setRunSpeed(float v) {
runSpeed = v;
}
virtual float getRunTime(float dis) {
return dis/runSpeed;
}
};
class Bird : public Animal{
public:
float flySpeed;
virtual void setSpeed(float v) {
flySpeed = v;
}
virtual float getFlyTime(float dis) {
return dis/flySpeed;
}
};
class Swallow : public Bird {
};
class BrownKiwi : public Animal {
};
int main(){
Bird* b1 = new Swallow; // &b1 是
Animal* b2 = new BrownKiwi;
b1->setSpeed(300);
b1->setRunSpeed(0.01);
b2->setRunSpeed(0.2);
std::cout<<"b1 fly time is: " << b1->getFlyTime(300)<<std::endl;
std::cout<<"b1 run time is: " << b1->getRunTime(300)<<std::endl;
std::cout<<"b2 fly time is: " << b2->getRunTime(300)<<std::endl;
return 1;
}
————————————————
版权声明:本文为CSDN博主「龙俊杰的读书笔记」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011852872/article/details/126048726
————————————————
版权声明:本文为CSDN博主「LoveLion」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lovelion/article/details/7540445