SOLID学习笔记 - 里氏替换原则

里氏替换原则(LSP) 任何父类出现的地方,都应该可以用它的子类替代,并且不会导致程序逻辑出错。子类能替换父类,并保持行为正确。原则理解方式记忆口诀✅ 里氏替换原则子类能替换父类,行为不崩溃“不是你的儿子,不要继承你”🚨 如何避免抽象设计精准、使用接口拆分“不要滥用继承,改用组合或接口” 阅读详情

六大设计原则

  里氏替换原则:

    “子类型必须可替代其基本类型”。换句话说,给定一个特定的基类,从它继承的任何类都可以替代基类。

    错误示例:

class LSPDemo
{
    static void Main(string[] args)
    {
        Rectangle shape;
        shape = new Rectangle();
        shape.SetWidth(14);
        shape.SetHeight(10);
        Console.WriteLine("Area={0}", shape.Area); // 140        

        shape = new Square();
        shape.SetWidth(14);
        shape.SetHeight(10);
        Console.WriteLine("Area={0}", shape.Area); // 100
        Console.ReadLine();
    }
}

public class Rectangle
{
    protected int _width;
    protected int _height;

    public int Width
    {
        get { return _width; }
    }

    public int Height
    {
        get { return _height; }
    }

    public virtual void SetWidth(int width)
    {
        _width = width;
    }

    public virtual void SetHeight(int height)
    {
        _height = height;
    }

    public int Area
    {
        get { return _height * _width; }
    }
}

public class Square : Rectangle
{
    public override void SetWidth(int width)
    {
        _width = width;
        _height = width;
    }

    public override void SetHeight(int height)
    {
        _width = height;
        _height = height;
    }
}

运行此代码将导致第一个形状的面积为 140,第二个形状的面积为 100。然后,您会想启动调试器以找出发生了什么。子类的行为已更改。用 Uncle Bob 的话来说,代码违反了 LSP,因为子类型不能替代其基类型。现在我们都知道正方形和矩形是不一样的,但这表明正方形不是矩形的特殊类型。

这是大多数关于LSP的讨论停止的地方。但是 LSP 比这个简短的示例更复杂。LSP 实际上执行了几条规则。这些规则分为两类,合同规则和差异规则。让我们更深入地研究一下这些规则。

合同规则

创建类时,协定以正式术语说明如何使用该对象。您需要将方法的名称以及这些参数的参数和数据类型作为输入,然后期望将哪种数据类型作为返回值。LSP 对合同规则施加了三个限制:

· 子类型无法加强前置条件 – 前置条件是方法可靠运行所需的条件。这将要求正确实例化类,并将所需的参数传递给方法。通常,保护子句用于强制参数具有正确的值。

· 后置条件不能在子类型中被削弱 – 后置条件验证当方法返回时对象是否处于可靠状态。保护子句再次用于强制执行后置条件。

· 超类型的不变量必须由子类型保留 – 不变量是对象构造完成后,在对象的生存期内必须保持为真的事物。这可能是在构造函数中设置并假定不会更改的字段值。子类型不应将这些类型的字段更改为无效值。例如,可能存在一个业务规则,即最低运费字段必须大于或等于零。子类型不应使其成为负数。只读字段保证遵循此规则。

超差规则

在解释方差规则之前,我们需要定义方差。以下是维基百科所说的,“方差是指更复杂类型之间的子类型如何与其组件之间的子类型相关联......C# 接口中的方差由其类型参数上的输入/输出注释确定“https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)”。这相当复杂。可以这样想,你期望不同但相关的亚型如何表现?这就是差异。现在,以下是 LSP 差异规则:

·子类型中必须存在方法参数的逆变 – 子类型反转类型的顺序。

·子类型中方法的返回类型必须存在协方差 – 子类型使类型保持从特定到最泛型的相同顺序。

·子类型不应引发新的异常,除非这些异常是基类型引发的异常的子类型 – 此规则简单且不言自明。

如果推断这些规则,则会发现子类型无法接受更具体的类型作为参数,并且不能返回不太具体的类型作为结果。

利斯克的解决方案

现在我已经展示了LSP不是什么并解释了它是什么,我想向您展示一个李氏原理的例子。问题是,我们需要用正方形代替矩形,反之亦然,只改变实例化的类。但是,在创建正方形时,如果我们传递两个高度和宽度参数,那么哪个参数是正确的呢?我们可以要求您传递相同的数字两次,但这似乎毫无用处,因为只需要一个。归根结底,上面的代码可以很好地显示Liskov不是什么,但是当您尝试显示Liskov是什么时,它不能很好地工作。所以,我必须转向另一个例子。

我决定使用基本类型的动物。当然,这不是一个完美的例子,因为有些动物跳跃,有些动物滑行,行走或疾驰。有些会飞,有些则不会。有些人有脚,有些人没有。但我认为它仍然会显示如何将一个子类替换为另一个子类。

class Program
{
    static void Main(string[] args)
    {
        Animal animal = new Dog();
        Console.WriteLine(animal.Walk());
        Console.WriteLine(animal.Run());
        Console.WriteLine(animal.Fly());
        Console.WriteLine(animal.MakeNoise());
        Console.ReadLine();
    }
}

public class Animal
{
    public string Walk()
    {
        return "Move feet";
    }
            
    public string Run()
    {
        return "Move feet quickly";
    }

    public virtual string Fly()
    {
        return null;
    }

    public virtual string MakeNoise()
    {
        return null;
    }
}

public class Dog : Animal
{
    public override string MakeNoise()
    {
        return "Bark";
    }
}

public class Bird: Animal
{
    public override string MakeNoise()
    {
        return "Chirp";
    }

    public override string Fly()
    {
        return "Flag wings";
    }
}

如果为 Dog 运行此代码,则将获得以下输出。

Move feet
Move feet quickly

Bark

请注意 Fly( ) 的空行。狗不会飞,所以什么都没回。现在把狗改成鸟,你得到

Move feet
Move feet quickly
Flag wings
Bark

如果您现在将Bird更改为Animal,会发生什么情况?

Move feet
Move feet quickly

子类(狗或鸟)可以替换为基类(动物),一切仍然有效。代码本身并不关心。我们还可以更进一步,使用 Factory 方法来创建我们想要使用的类,而代码甚至根本不知道该类。但这超出了这个讨论的范围。

瑞芯微RK3506开发板Ethercat主站性能优化实战:从内核配置到微秒级延迟控制 本文详细介绍了在瑞芯微RK3506开发板上实现EtherCAT主站微秒级延迟控制的实战优化方案。核心在于部署Preempt-RT实时内核,并进行深度系统调优,包括CPU隔离、中断亲和性设置、内存锁定及电源管理调整。通过绕过Linux网络栈的专用驱动加载与配置,最终实现了稳定的高性能实时控制,满足工业自动化需求。 阅读详情

相关推荐

ROS2机械臂MPC轨迹规划实战:从MoveIt 2插件配置到参数调优全流程

本文详细介绍了ROS2机械臂MPC轨迹规划的全流程,从MoveIt 2插件配置到参数调优。通过模型预测控制(MPC)技术,实现高精度运动控制,特别适合复杂装配任务。文章包含环境搭建、插件部署、参数设计及实战调优方法,帮助开发者快速掌握ROS2机械臂的MPC轨迹规划技术。

i0j1k2l3m的博客 206

SOLID原则:里氏替换原则(LSP)

SOLID:SOLID原则并非单纯的1个原则,而是由5个设计原则组成,它们分别是:单一职责原则、开闭原则、里式替换原则、接口隔离原则和依赖反转原则,SOLID由5个设计原则的头一个字母组成。 如何理解里氏替换原则? 里氏替换原则(Liskov Substitution Principle,LSP),这个原则最早是在1986年由Barbara Liskov提出,他是这么描述这条原则的: If S is a subtype of T, then objects of type T may be repla.

Vincent的博客 670

DSMA时序修复避坑指南:当Setup和Hold互卡时,除了调Margin还能做什么?

本文深入探讨DSMA时序修复中的Setup与Hold互锁问题,提供7种高阶策略,包括优先级判断、高级参数组合、单元类型智能替换等,帮助工程师突破时序收敛瓶颈。特别针对fix_eco_timing命令的隐藏参数和物理协同优化进行详细解析,助力芯片设计实现时序收敛。

weixin_30162121的博客 295

经济理性AI办公助手:OmegaUse-OfficeVal基准如何重塑LLM智能体评估

在人工智能与办公自动化深度融合的背景下,大语言模型(LLM)智能体正从简单的指令执行向复杂任务处理演进。其核心原理在于通过自然语言理解与工具调用,模拟人类完成跨软件、多步骤的办公流程。这项技术的价值在于将人力从重复性劳动中解放出来,提升工作效率与决策质量,广泛应用于报告生成、数据分析、会议安排等场景。然而,传统评估方式往往只关注功能实现,忽视了资源消耗与成本效益。OmegaUse-OfficeVal基准测试的提出,正是为了解决这一问题。它创新性地引入了**经济属性**与**能量预算**机制,模拟真实办公环境

weixin_34183910的博客 469

快乐8 Ai大模型XGBoost LightGBM预测系统

随机森林回归:通过集成多个决策树模型,提高预测的准确性和稳定性。XGBoost:一种基于梯度提升的强大模型,擅长处理结构化数据。LightGBM:一种高效的基于决策树算法的分布式梯度提升框架,具有快速的训练速度和低内存消耗。高预测准确率:通过集成多种模型,提供更为精准的预测结果。多种预测方法:支持同尾号、重号、温号、连号和综合预测等多种预测策略,满足不同用户的需求。实时日志:在预测过程中,用户可以实时查看系统的预测进度和结果。

m0_72636583的博客 1万+

osgEarth shapefile矢量生成三维模型案例 2.boston.earth

osgEarth shapefile矢量生成三维模型案例 2.boston.earth 波士顿城市建筑、路灯、公园、道路shp矢量生成三维模型案例。

qq_24934183的博客 3543

SOLID 原则之里氏替换原则

这是 SOLID 安卓开发系列原则的第三部分。如果你错过了第一部分或者你不熟悉 SOLID 原则,请看 第一部分,这里我们介绍了 SOLID 而且讨论了单一职责原则,和 第二部分,这里我们讨论了开闭原则。里氏替换原则SOLID 缩写的第三个字母是 L,代表着里氏替换原则(LSP)。里氏替换原则在 1987 年的一次会议的演讲上由 Barbara Liskov 提出。里氏替换原则如下描述:一个程序里...

大后生大大大的博客 503

IEDA激活码失效?教你5分钟快速续期的方法

本文针对IEDA激活码失效问题,提供了一套从快速应急到深度排查的完整解决方案。文章不仅详解了5分钟快速续期与清理缓存等应急方法,更深入剖析了授权机制、离线激活流程,并指导如何构建可持续的授权管理策略,帮助开发者彻底解决激活困扰,确保开发环境稳定。

a0b1c2d3的专栏 273

快速理解 SOLID (面向对象设计)——里氏替换原则

快速理解 SOLID (面向对象设计)——里氏替换原则 在程序设计领域, SOLID(单一功能、开闭原则、里氏替换、接口隔离以及依赖反转),指代了面向对象编程和面向对象设计的五个基本原则。当这些原则被一起应用时,它们使得一个程序员开发一个容易进行软件维护和扩展的系统变得更加可能。 1. 里氏替换原则 1.1 里氏替换原则 的定义 里氏替换原则这个名字使很多人产生了疑惑,其实里氏替换原则是由麻...

qq_18208265的博客 359

2026年职业院校技能大赛中职移动应用与开发模块二10套题库开发培训视频(全套)

2026年职业院校技能大赛中职移动应用与开发模块二10套题库开发培训视频(全套)

我是网络安全兼技能大赛工程师,专注网络安全技术学习与技能大赛实战!持续分享最新的技术文章,帮你少走弯路,一起在技术赛道上进步~ 352

【软考高项】【计算专题】- 3 - 进度类 - 双代号网络图

共需压缩 20 天。在双代号网络图中,工作一般使用箭线表示,任意一条箭线都需要占用时间、消耗资源,工作名称写在箭线的上方,而消耗的时间则写在箭线的下方或者工作后面。反映的是前后工作的交接点,节点中的编号可以任意编写,但应保证后续工作的节点比前面节点的编号大,即上图图中的1⃣️4⃣️ 即表示 B 活动和 D 活动间有依赖关系,D 活动的开始,依赖 B 活动的结束。B活动完成了一半, 各计划的实际支出为A活动6500元, B活动1000元, C活动280元, D。

欢迎来到我的博客,一起探索代码里的世界! 4561

里氏替代原则 (LSP) :深入了解SOLID 原则

在软件工程领域,对创建可维护、可扩展和灵活代码的追求永无止境。实现这一目标的最完善的一套原则是 SOLID 原则,由 Robert C. Martin 创造。几十年来,这些原则一直是设计和构建面向对象代码的基础,旨在降低代码的复杂性,使其更易于理解,从而更易于维护。

sinat_26065899的博客 745

2026.2.3:OpenClaw国内安装教程,国内网络使用,服务器部署,对接飞书

本文介绍了如何创建飞书应用并接入OpenClaw机器人的完整流程。主要内容包括:1)在飞书开放平台创建企业自建应用,添加机器人能力并开通相关权限;2)在Windows11系统上安装OpenClaw,完成配置文件的修改(需将bind改为"lan");3)配置MiniMax国内接口地址,重启gateway服务。整个过程涵盖了应用创建、权限设置、软件安装、服务配置等关键步骤,为开发者提供了详细的飞书机器人接入指南。

拥抱具身智能,昇腾Ascend C 3993

Python:里氏替换原则(LSP)

Square 改变了父类 Rectangle 的关键行为契约(宽高修改的独立性),导致在需要 Rectangle 的场景中无法正确替换 Rectangle,从而违反了 LSP。里氏替换原则就像“标准插头规范”:任何子类都必须遵守父类定义的接口和行为规范,才能在父类能工作的场景中无缝替换使用。如果 S 是 T 的子类型,那么类型 T 的对象可以被类型 S 的对象替换,而不会改变程序的正确性。改进:创建 Writer 抽象基类;LSP 的意义就是确保继承结构的正确性,使子类是真正的父类扩展,而不是破坏父类。

qq_41176800的博客 1581

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

SOLID原则学习,里氏替换原则(Liskov Substitution Principle, LSP)

里氏替换原则的核心是确保子类可以完全替换父类而不影响程序的正确性。通过合理设计类的继承关系,避免子类修改父类的行为,可以提高代码的可维护性和可扩展性。在实际开发中,如果发现子类无法完全替换父类,可能需要重新审视类的设计,考虑使用组合或其他设计模式来解决问题。

汽车电子软件领域知识分享 1338

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

整洁架构SOLID-里氏替换原则(LSP)

LSP可以且应该被应用于软件架构层面,因为一旦违背了可替换性,该系统架构就不得不为此增添大量复杂的应对机制。

贾欣晓的博客 1111

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【设计原则】里氏替换原则(LSP):构建稳健继承体系的黄金法则

里氏替换原则(Liskov Substitution Principle, LSP)是面向对象设计SOLID原则中的"L",由Barbara Liskov在1987年提出。所有引用基类(父类)的地方必须能透明地使用其子类的对象子类必须完全实现父类的抽象方法子类可以扩展父类功能但不能改变原有行为子类方法的前置条件不应强于父类子类方法的后置条件不应弱于父类优先使用组合而非继承保持继承层次扁平化使用设计模式:策略模式模板方法模式装饰器模式定期进行代码审查编写契约测试。

OpenSeek的博客 1989

深入理解设计原则之里氏替换原则(LSP)【软件架构设计】

里氏替换原则(Liskov Substitution Principle, LSP)于1986年有Barbara Liskov提出,他当时是这样描述这条原则的:如果S是T的子类型,那么T的对象可以被S的对象所替换,并不影响代码的运行。1996年,Robert Martin在他的SOLID原则中重新描述了里氏替换原则:使用父类对象的函数可以在不了解子类的情况下替换为使用子类对象。 结合上面的描述,我们将里氏替换原则描述为:子类对象能够替换到程序中的父类对象出现的任何地方,并且保证程序原有的逻辑行为不变和正确性

weixin_30197685的博客 3441

里氏替换原则是什么?gh_mirrors/so/solid.python项目带你轻松掌握

里氏替换原则(Liskov Substitution Principle,LSP)是SOLID五大设计原则之一,由Barbara Liskov提出。在gh_mirrors/so/solid.python项目中,这一原则通过简洁的Python代码示例得到了生动诠释,帮助开发者理解如何构建灵活可扩展的面向对象系统。 ## 🌟 里氏替换原则的核心思想 简单来说,里氏替换原则要求**子类必须能够替换

gitblog_00370的博客 876

设计原则—SOLID(LSP)

Liskov Substitution Principle,缩写为 LSP。这个原则最早是在 1986 年由 Barbara Liskov 提出 子类对象(object of subtype/derived class)能够替换程序(program)中父类对象(object of base/parent class)出现的任何地方,并且保证原来程序的逻辑行为(behavior)不变及正确性不被破坏。 里式替换原则还有另外一个更加能落地、更有指导意义的描述,那就是“Design By Contrac“

3万+

如何掌握PHP里氏替换原则:clean-code-php中的LSP实践指南

**clean-code-php**是一个专注于将Clean Code概念应用于PHP开发的开源项目,提供了包括里氏替换原则(LSP)在内的多种代码设计规范。本文将通过通俗的语言和实际场景,帮助开发者理解LSP原则的核心思想及其在PHP项目中的落地方法。 ## 什么是里氏替换原则(LSP)? 里氏替换原则由计算机科学家Barbara Liskov提出,是面向对象设计的五大基本原则(SOLID)

gitblog_00391的博客 1124

SOLID软件设计原则之LSP与DIP

SOLID软件设计原则之SRP SOLID软件设计原则之OCP原则 人们常常高估了一天能做的事情,却低估了一年能得到的成就。时间倏忽而过,转眼五一小长假只剩下最后一天,放假前列出的清单还有两三件没有完成,无论如何,依然按照计划在最后一天看看书,梳理一下思路,准备迎接5月的紧张工作。 软件设计五大原则之前简单整理了两个:单一指责原则(SRP)和开放/封闭原则(OCP),文章链接见本文开头。今天...

牧羊女 599

SOLID五大原则【图解】

做C语言开发的应该都知道,C是面向过程开发的,而c++是面向对象开发的。而封装、继承与多态是面向对象开发的三大特征。 但你可能不知道OOD(Object-Oriented Design)还有五大基本原则,被Bob大叔称为SOLID原则,字母为每个原则的首字母,遵循这些原则能够让你的代码在扩展性、维护性以及重用性提高。而这些不正是我们所追求的吗?......

Somnus陳的博客 9190

SOLID之LSP-里氏替换原则

SOLID之LSP-里氏替换原则

just_for_that_moment的博客 341

LSP和SOLID原则

LSP和SOLID的介绍

tu_gou的博客 263

里氏替换原则(LSP)

里氏替换原则(英文名为Liskov substitution principle,简称LSP)是由Barbara Liskov在1988年提出的,在Robert C. Martin提出的SOLID软件设计原则中的第二个字母L。 挑出一个相对比较容易明白的定义: if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of t

一个程序员的修炼之路 1837
上一篇: SOLID 学习笔记 - 单一职责
oopts
博客等级 码龄9年 0粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值