里氏代换原则 举例 分析

里氏代换原则 举例 分析里氏代换原则定义 里氏代换原则 LiskovSubsti 面向对象设计的基本原则之一 目的 里氏代换原则中说 任何基类可以出现的地方 子类一定可以出现 LSP 是继承复用的基石 只有当衍生类可以替换掉基类 软件单位的功能不受到影响时 基类才能真正被复用 而衍生类也能够在基类的基础上增加新的行为 价值 里氏代换原则是对 开 闭 原则的补充 实现 开 闭

里氏代换原则
定义:里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。
目的:里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
价值:里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
说实话,“任何基类可以出现的地方,子类一定可以出现”,这话太抽象了,我根本找不出另例子来证明,什么是符合这个原则的,什么是不符合这个原则的。
子类一定可以出现,从语言的基本要求角度来讲,这是必须的,面向对象中父类就是可以被子类替换的,那么这个要求针对的是啥?
是需求的层面,因为子类替换父类,在技术上一定是允许的,那么我们在设计上要加些什么样的限制来保证这一点呢。
一个一个的举例吧:
1.类作为函数的参数:函数(类)
这种情况,那对该函数的设计要求是:该函数不能处理个性的需求,也就是说,不应该去处理基类中某一类型所特有的机能,否则这个函数设计不合格。
对类的设计要求是:个性的东西一定要自己处理,不能公开。
2.类做未一个调用函数的对象:类.函数()
这种情况,对该函数的设计要求是,该函数必须处理的是共性的内容,个性的内容要用通过this指针去处理。
























// 长方形 class Rectangle{ 
    private: int h; int w; public: void setH(int value){ 
    h = value; } void setW(int vaule){ 
    w = vaule; } int getH(){ 
    return h; } int getW(){ 
    return w; } }; // 正方形 class Square:public Rectangle{ 
    void set(int value){ 
    setH(value); setW(value); } }; 

二.到这来应该是没有问题的,因为LSP是一个需求级别的设计要求。
现在假设有这么一个要求,保证长方形的宽度一定要大于高度。
函数如下:




class Clinet{ 
    public: void setRectangle(Rectangle* r){ 
    if(r->getW()<r->getH()){ 
    r->setW(r->getH()+1); } } }; 
// 长方形 class Rectangle{ 
    private: int h; int w; public: void setH(int value){ 
    h = value; } void setW(int vaule){ 
    w = vaule; } int getH(){ 
    return h; } int getW(){ 
    return w; } //设计变更 virtual void setRectangle(){ 
    if(getW()<getH()){ 
    setW(getH()+1); } } }; // 正方形 class Square:public Rectangle{ 
    void set(int value){ 
    setH(value); setW(value); } //设计变更 virtual void setRectangle(){ 
    } }; class Clinet{ 
    public: void setRectangle(Rectangle* r){ 
    //设计变更 r->setRectangle(); } }; 
class Quadrilateral{ 
    protected: int h; int w; public: virtual void setH(int value)=0; virtual void setW(int vaule)=0; virtual int getH()=0; virtual int getW()=0; }; // 长方形 class Rectangle: public Quadrilateral{ 
    public: virtual void setH(int value){ 
    h = value; } virtual void setW(int vaule){ 
    w = vaule; } virtual int getH(){ 
    return h; } virtual int getW(){ 
    return w; } }; // 正方形 class Square:public Quadrilateral{ 
    private: void setSide(int value){ 
    h = w = value; } public: virtual void setH(int value){ 
    setSide(value); } virtual void setW(int vaule){ 
    setSide(vaule); } virtual int getH(){ 
    return h; } virtual int getW(){ 
    return w; } }; class Clinet{ 
    public: void setRectangle(Rectangle* r){ 
    if(r->getW()<r->getH()){ 
    r->setW(r->getH()+1); } } }; //客户端调用 int main() { 
    cout<<"建造者模式演示\n"; //看代码不用考虑以下内容 int cin_a; cin>>cin_a; return 0; } 

总结
设计无非就是解决共性和个性的问题,LSP做为一个原则,其实我们即使不学这个原则,也不一定不会遵守这个原则,因为如果你真的做了一个不符合这个原则的设计,那么运行马上就会遇到问题。
解决好共性和个性,就一定是一好的设计,一个符合各种设计原则的设计。
对于LSP这个原则,我其实一直都是理解的云里雾里的,直到现在才把这个东西具体化,所以,我觉得什么抽象的东西都试着举例说明,要不然你永远不会有一个清晰的思路。






版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216414.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午11:54
下一篇 2026年3月18日 上午11:54


相关推荐

  • Petshop4学习

    Petshop4学习Petshop4的研究分析:http://blog.csdn.net/sjklove/archive/2006/11/10/1377405.aspx1.项目概述与架构分析微软刚推出了基于ASP.NET2.0下的PetShop4,该版本有了一个全新的用户界面。是研究ASP.NET2.0的好范例啊,大家都知道,一直以来,在.NET和Java之间争论不休,到底使用哪个平台开发的企业级应用性…

    2022年10月17日
    4
  • python究竟要不要使用多线程

    (1)python多线程究竟有没有用?(2)python虚拟机机制如何控制代码的执行?(3)python中多进程处理原理是怎么样的?1.先来看两个例子(1)例1分别用单线程、使用多线程、使

    2021年12月29日
    48
  • 转:Ubuntu 更换国内源

    转:Ubuntu 更换国内源Ubuntu 系统自带的源都是国外的网址 国内用户在使用的时候网速比较慢 一个软件的下载是十分痛苦的 这里讲解一下如何将国外源更换为国内源 让你的网速 Biu Biu Biuc 如果想快速切换国内源强烈推荐 gt gt gt gt Ubuntu 快速更换国内源 lt lt lt lt 该篇博国内源是 16 04 推荐使用 gt gt gt Ubuntu 快速更换国内源 lt lt lt lt 该篇博国内源是 16 04 推荐使用

    2026年3月17日
    2
  • 后缀表达式、前缀表达式

    后缀表达式、前缀表达式后缀表达式和前缀表达式是什么呢 nbsp nbsp nbsp nbsp nbsp 前缀表达式 不包括括号的算术表达式 将运算符写在前面 操作数写在后面的表达式 为纪念其发明者波兰数学家 JanLukasiewc 也称 波兰式 nbsp nbsp nbsp nbsp nbsp 后缀表达式 不包括括号 运算符放在两个运算对象的后面 所有的计算按运算符出现的顺序 严格从左向右进行 也称 逆波兰式 nbsp nbsp nbsp nbsp nbsp 举个栗子 nbsp nbsp nbsp nbsp nbsp nbsp

    2026年3月19日
    2
  • FM系列算法解读(FM+FFM+DeepFM)

    FM系列算法解读(FM+FFM+DeepFM)https://blog.csdn.net/jiangjiang_jian/article/details/80631180

    2022年6月12日
    42
  • python 的IDEA激活码_通用破解码

    python 的IDEA激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    143

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号