深度解析:设计模式七大原则之——里氏替换原则

Java设计原则:SOLID与七大核心原则实践指南 面向对象设计原则是构建可维护软件系统的理论基础,其中SOLID原则(单一职责、开闭原则、里氏替换、接口隔离和依赖倒置)尤为关键。这些原则通过抽象和封装解决代码耦合问题,提升系统的扩展性和可测试性。在Java开发中,合理应用这些原则能有效应对需求变更,特别是在微服务架构和复杂业务系统中。本文以用户管理系统为例,展示如何通过接口隔离和依赖注入实现松耦合,同时结合迪米特法则控制对象间的交互边界。对于常见问题如巨型类和过度继承,遵循组合优于继承原则往往能带来更灵活的设计。 阅读详情

临近端午节,各位读者,你们假期行程安排好了吗?“菜鸟”已经做好决定了,谁都不能阻拦(产品经理也不行),“菜鸟”要好好在家休息三天。最近实在是太累了,一直在疯狂的加班。

在这里插入图片描述

好了好了言归正传,开始我们的正文。今天由“菜鸟”为大家分享一下设计模式七大原则中的“里氏替换原则”。讲该原则之前我们不得不提一下面向对象对象的三大特性,它们分别是:封装、继承、多态。相信了解面向对象编程的程序员,对这三大特性肯定不会陌生。

那么肯定就有人会产生疑问了,这三大特性跟我们今天的内容有什么关系吗?别慌且听“菜鸟”慢慢诉说,我们今天分享的“里氏替换原则”就是专门为“继承”所准备的。

在这里插入图片描述

我们应该都知道使用继承也是存在弊端的,它会给程序带来侵入性,并且降低程序的可移植性,还会增加对象之间的耦合性。当父类需要修改时,需要考虑到所有的子类,盲目修改父类,有可能会造成子类的功能产生异常。

为了减少这些弊端,就产生了“里氏替换原则”,该原则是1988年由麻省理工一位名为Barbara Liskov的女士提出。通过其名称,我们应该能看出来该原则的重点就在“替换”这两个字上。

该原则的核心思想就是在程序当中,如果将一个父类对象替换成它的子类对象后,该程序不会发生异常。这也是该原则希望达到的一种理想状态。

下面就让我们从四个方面来深入了解一下里氏替换原则。

第一点

讲第一点之前我们先思考在“继承”中会面临的这样一个问题:我们的父类定义好的方法,并不会强制要求其子类必须完全遵守该方法的实现规则。子类是可以修改它继承自父类的任意方法的。

如以下代码所示:

public class Demo {

  public static void main(String[] args) {
    Superclass superclass = new Superclass();
    superclass.add(3, 2);
    Son son = new Son();
    son.add(3, 2);
  }

}

/**
 * 父类
 */
class Superclass {

  public void add(int num1, int num2) {
    int value = num1 + num2;
    System.out.println("父类计算出的结果为:" + value);
  }
}

/**
 * 子类
 */
class Son extends Superclass {

  @Override
  public void add(int num1, int num2) {
    int value = num1 - num2;
    System.out.println("子类计算出的结果为:" + value);
  }
}

父类的本意是想要定义一个两数相加的方法,但是子类继承该方法后却修改为减法,并且也成功了。子类这样操作后,会对整个继承体系造成破坏。当你想把使用父类的地方替换为其子类时,会发现原来的正常的功能现在出现问题了。

在这里插入图片描述

为了解决此问题,就有了里氏替换原则的第一点:

子类可以实现父类中的抽象方法,但是不能重写(覆盖)父类的非抽象方法。

如果我们严格遵守该原则就不会产生上面的问题。

第二点

当我们迫不得已需要在子类中添加一个跟父类方法名称相同的方法时,就需要遵守下面这点。

当子类需要重载父类中的方法的时候,子类方法的形参(入参)要比父类方法输入的参数更宽松(范围更广)。。

这句话的意思大家能明白嘛?不是特别清楚也不用着急,请看下面的代码。

/**
 * 父类
 */
public class Superclass {


  public void method(ArrayList arrayList) {
    System.out.println("父类方法执行了!");
  }
}

/**
 * 子类
 */
public class Son extends Superclass {

  // 重载了父类的method,并且方法入参比父类的入参范围更广。
  public void method(List list) {
    System.out.println("子类方法执行了!");
  }
}

那么这样做有什么意义那,目的又是为了什么那?大家可以先思考一下。

在这里插入图片描述

其实很简单,这样做最直接的一个目的就是防止我们将父类对象替换为子类对象后,造成方法调用混乱的问题。

请看下面测试代码和其执行结果:

  public static void main(String[] args) {
    ArrayList list = new ArrayList();
    Superclass superclass = new Superclass();
    Son son = new Son();
    System.out.print("使用父类对象调用的结果:");
    superclass.method(list);
    System.out.print("将父类对象替换成子类对象后的调用结果:");
    son.method(list);
  }

执行结果如下:

在这里插入图片描述

如果没有遵守上面的规则的话就会造成很大的麻烦,请看下列示例代码。

public class Demo2 {

  public static void main(String[] args) {
    ArrayList list = new ArrayList();
    Superclass superclass = new Superclass();
    Son son = new Son();
    System.out.print("使用父类对象调用的结果:");
    superclass.method(list);
    System.out.print("将父类对象替换成子类对象后的调用结果:");
    son.method(list);
  }

}

/**
 * 父类
 */
class Superclass {

  public void method(List arrayList) {
    System.out.println("父类方法执行了!");
  }
}

/**
 * 子类
 */
class Son extends Superclass {

  public void method(ArrayList list) {
    System.out.println("子类方法执行了!");
  }
}

测试结果如下:

在这里插入图片描述

确实发生问题了吧!我们的本意是希望对象替换后还执行原来的方法的,可结果却发生变化了。这样是不符合里氏替换原则的。所以我们要时刻牢记,子类方法的入参要比父类的入参范围更大,这样才不会造成不必要的错误。

第三点

当我们需要重写或者实现父类方法时,需要遵守下面这一点。

重写或者实现父类方法的时候,方法的返回值可以被缩小,但是不能放大。

示例代码:

/**
 * 父类
 */
public class Superclass {

  public List getList() {
    return new ArrayList();
  }
}

/**
 * 子类
 */
public class Son extends Superclass {

  @Override
  public ArrayList getList() {
    return new ArrayList();
  }
}

如果我们试图在子类中放大,重写或实现来自父类方法的返回值时,代码会报错,连基本的编译器都无法通过。

第四点

子类可以拥有自己独特的方法或属性。

这句话就更好理解了,它说明子类不光可以拥有从父类继承来的东西,也可以进行自我扩展,编写属于自己的东西。

这一点相信大家都明白,我就不在编写示例代码了。

总结

通过上面的描述相信大家都对里氏替换原则有了一个基本的概念,其实它就是告诉我们在继承中需要注意什么问题和遵守什么规则。

然而在实际开发中我们在很多时候还是会违背该原则的,虽然表面上没有什么特别大的问题,但是这样做会大大增加代码的出错率。我们编写代码时不光要考虑怎么实现该功能,程序的健壮性和后期的扩展以及移植都是需要考虑到的。只有这样做才可以使我们的程序更加优秀。

好了今天的分享就到这里了,如果感觉“菜鸟”的文章写的还不错的,记得点赞加关注呦!你们的支持就是我坚持下去的动力。

远程桌面报‘数据加密错误‘?可能是网卡设置惹的祸(附TCP校验关闭教程) 本文深入分析远程桌面连接中出现的'数据加密错误'问题,指出网卡设置可能是根本原因,并提供详细的TCP校验关闭教程。通过禁用网卡高级属性中的'TCP校验和IPv4'与'IPv4承载卸载'功能,可有效解决RDP协议与硬件加速的兼容性问题,适用于Windows和Linux系统。 阅读详情

相关推荐

多节阶梯阻抗变换器工程设计的公式推导

  多节阶梯阻抗变换器工程设计的公式推导,仔细看此文,有点烧脑,所以碎片十分钟,收获一丢丢。   现在就来设计一个超宽带多节阶梯阻抗变换器,要求带内纹波符合切比雪夫分布。   其实,此文已经是省去了大量中间公式推导,只剩下精炼内容了。   阶梯阻抗变换器指标需求   假设现在有一项目需求分析结果是:做一个微带线超宽带阶梯阻抗变换器,指标如下:   从50欧变换到100欧;   回波损耗22dB;   功率容量:2W;   频率范围2~18GHz;   插损能做多少就多少,用30mil板厚.

wusuowei1010的博客 7805

里氏替换原则——举例说明Java设计模式中的里氏替换原则

里氏替换原则——举例说明Java设计模式中的里氏替换原则1. 前言官方定义:2. 举例说明2.1 例子介绍2.2 反例2.2.1 类图说明2.2.2 代码说明2.2.3 测试2.2.4 分析优缺点2.3 正例2.3.1 类图说明2.3.2 代码说明(1)抽取基类(父类)-->ChooseSweater(2)倾向中性服饰子类-->NeutralChooseSweater(3)倾向女性服饰子类-->GirlChooseSweater2.3.3 测试2.3.4 分析优缺点3. 总结使用继承?如何

@素素~的博客 1873

MATLAB App Designer 实现多窗口交互与数据传递实战

本文详细介绍了如何使用MATLAB App Designer实现多窗口交互与数据传递的实战技巧。从基础的多窗口应用设计到高级的动态窗口创建,涵盖了窗口调用控制、数据传递方法、状态管理及用户体验优化等核心内容,帮助开发者高效构建复杂的MATLAB GUI应用。

milk5的博客 663

设计原则之里氏替换原则详解

一、里氏替换原则定义 定义: 如果对每一个类型为T1的对象O1,都有类型为T2的对象O2,使得所有以T1定义的所有程序P在所有的对象O1都替换成O2时,程序P的行为没有发生任何变化,那么类型T2是类型T1的子类型。 通俗理解就是:子类可以扩展父类的功能,但不能改变父类原有的功能。有以下几个引申含义: 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。 子类中可以增加自己特有的方法。 当子类的方法重载父类的方法时,方法的前置条件(方法的输入,入参)要比父类的入参更宽松。 当子类的方法实现父类的方法时(

qq_38925911的博客 6111

Fritzing0.9.10下载安装和简单使用

Fritzing 作为一款电子设计自动化软件,其画图用于导入到论文和文档,清晰好看,能解决用相机拍实物照片杜邦线很乱的痛点。

李同学Lino的博客 3万+

黑苹果从入门到精通:最详细的VMware安装macOS教程

前言 不知为何,以前我发的两篇关于黑苹果的文章或没过审或被删除,最近SMZDM上有不少优质的黑苹果文章发出来,貌似禁令已开,前段时间在一篇写的很不错的黑果文章下吹牛说今年要写一个系列,故有了这篇文章作为系列的开头。 系列的名字起的有点俗,叫做xxx从入门到精通,但是我很喜欢,相信过半的黑果群众都是程序员,作为教程来说这个名字俗但是好用,我也希望这个系列能像其它入门到精通系列一样,让大家学到东西...

La victoria的博客 14万+

设计模式六大原则:里氏替换原则详细说明和案例示范

子类对象可以替换父类对象,程序的行为不会发生变化。子类在扩展父类功能的同时,不能改变父类原有的行为。通俗地说,如果我们在程序中使用的是一个基类对象,那么在不修改程序的前提下,用它的子类对象替换这个基类对象,程序应该仍然可以正常运行。里氏替换原则是面向对象设计中的重要原则之一,它确保子类能够替换父类而不会影响系统的正确性。在设计系统时,遵循里氏替换原则可以帮助我们构建一个更稳定、可扩展的系统,避免因子类行为改变而引发的潜在问题。在实际开发中,建议开发人员在设计继承体系时,时刻考虑子类是否能够替代父类。

J老熊 2987

组态王|通过日历控件选择时间段查询历史报警

哈喽,你好啊,我是雷工!这节记录下查询历史报警信息的功能实现。以下为实现笔记。

做有价值的事,积累有价值的笔记! 3758

里氏替换原则

该原则的核心思想就是在程序当中,如果将一个父类对象替换成它的子类对象后,该程序不会发生异常。这也是该原则希望达到的一种理想状态。通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。里氏代换原则是开闭原则的重要方式之一,由于使用父类对象的地方都可以使用子类对象,因此在程序中尽量使用父类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。优点:1、代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原

weixin_39327556的博客 1万+

团体程序设计天梯赛竞赛题--登顶题【L3-039 攀岩】

登顶级 3 道题,每道题 30 分,满分为 90 分。

Pretty Boy Fox的博客 653

2026年CSP-J初赛真题及答案解析

2026年CSP-J初赛真题及题解

王老师青少年编程 1613

设计模式之里氏替换原则示例

设计模式之里氏替换原则示例  里氏替换原则强调的是设计和实现要依赖于抽象而非具体;子类只能去扩展基类,而不是隐藏或者覆盖基类,它包含4层含义. 一、里氏替换4原则   1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法   子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法,父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏...

Mario_3的博客 1651

单光子雪崩二极管(SPAD):原理、极高增益机制与微光探测解析

本文系统阐述了单光子雪崩二极管(SPAD)的工作原理及其在弱光探测中的应用。SPAD通过工作在盖革模式下的碰撞离化效应实现单光子探测,其核心机理包括:1)采用p+-n-n+结构实现高电场分布;2)通过雪崩倍增过程获得10^6量级增益;3)采用主动/被动淬灭机制实现快速恢复。文章详细分析了SPAD的关键性能参数(如光子探测效率、暗计数率等)及其在量子通信、激光雷达等领域的应用优势,揭示了该器件在极微弱光信号探测中的独特价值。

Fun_LiDAR的博客 1040

C# 设计模式七大原则深度解析:构建优雅代码的基石

设计模式的七大原则(SOLID + 另外两个常用原则)是面向对象设计的灵魂,它们指导我们构建灵活、可维护、可扩展的软件系统。本文我们先了解设计模式的七大原则,每个原则都会详细说明,提供示意图和C#代码示例。

2404_88212162的博客 1623

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

里氏替换原则_深度解析设计模式七大原则之——里氏替换原则

临近端午节,各位读者,你们假期行程安排好了吗?“菜鸟”已经做好决定了,谁都不能阻拦(产品经理也不行),“菜鸟”要好好在家休息三天。最近实在是太累了,一直在疯狂的加班。好了好了言归正传,开始我们的正文。今天由“菜鸟”为大家分享一下设计模式七大原则中的“里氏替换原则”。讲该原则之前我们不得不提一下面向对象对象的三大特性,它们分别是:封装、继承、多态。相信了解面向对象编程的程序员,对这三大特性肯定不会陌...

weixin_39968722的博客 146

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

设计模式七大原则深度解析与应用实践

通过电商系统的实际场景,我们展示了如何应用设计模式的七大原则,构建灵活、可维护的代码。

qq_53152589的博客 363

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

设计模式概述及七大原则

设计模式什么是设计模式为什么要使用设计模式设计模式七大原则 什么是设计模式 软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。 设计模式是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。 为什么要使用设计模式 代码重用性 可读性(规范性,阅读容易) 可扩展性(增加

street_boy的博客 379

【设计模式】一、设计模式七大原则

一、开闭原则 含义 当应用的需求改变时,在不修改软件实体的源代码或者二进制代码的前提下,可以扩展模块的功能,使其满足新的需求。 作用 开闭原则是面向对象程序设计的终极目标,它使软件实体拥有一定的适应性和灵活性的同时具备稳定性和延续性。具体来说,其作用如下。 对软件测试的影响 软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。 可以提高代码的可...

qwertyuiopasdfghjklzxcvbnm 739

初学设计模式的七大原则

初学设计模式

qq_43232096的博客 151

Java系统设计与面试深度解析:设计模式底层结合与Spring、MyBatis实战

在软件工程领域,设计模式(Design Pattern)是解决特定场景下常见问题的可复用方案。如同建筑大师克里斯托弗·亚历山大提出的建筑模式语言,软件设计模式为开发者提供了一套经过验证的"设计词汇"。这些模式不是具体代码实现,而是对优秀设计经验的抽象总结,能显著提升代码的可维护性、可扩展性和复用性。创建型模式(如工厂方法、抽象工厂、单例模式)关注对象创建机制结构型模式(如适配器、装饰器、代理模式)处理类与对象的组合行为型模式(如观察者、责任链、策略模式)定义对象间的交互方式。

zuiyuelong的博客 1196

面试官:设计模式的 7 大基本原则有哪些?

后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,:在重写方法时,子类的前置条件(对输入的要求)不能比父类更严格,后置条件(对输出的承诺)不能比父类更宽松。当需求变化时,我们通过增加新的代码(如新的子类、实现类)来扩展功能,而非修改现有的、稳定的代码。:OCP 不是绝对的,100% 的关闭不可能。:避免 "胖接口"。:确认你对面向对象设计(OOD)的核心思想有系统性的认知,这些原则是 OOD 的基石。

犬小哈 380

架构基石:深入理解软件开发七大设计原则

这七大原则并非孤立存在,而是相辅相成的。开闭原则是核心愿景,单一职责与接口隔离是组织手段,里氏替换依赖倒置与合成复用是实现路径,而迪米特法则则是解耦的润滑剂。在实际开发中,应权衡业务复杂度与设计成本,灵活运用这些规约,构建优雅的软件架构。

l3345973813的博客 489

软件设计原则

else if (type.equals("paypal")) { /* PayPal逻辑 */ }if (type.equals("credit")) { /* 信用卡逻辑 */ }class PayPal implements PaymentMethod { /* 实现 */ }void saveToDatabase() { /* 数据库操作 */ }void sendEmail() { /* 邮件通知 */ }void login() { /* 认证逻辑 */ }抽象不应依赖细节,细节应依赖抽象。

2301_81882590的博客 963

java设计模式深度理解分析

java23种设计模式 创建型模式 单例模式 抽象工厂模式 原型模式 建造者模式 工厂模式 结构性模式 结构性模式 适配器模式 桥接模式 装饰模式 组合模式 外观模式 享元模式 代理模式 行为型模式 模板方法模式 命令模式 访问者模式 迭代器模式 观察者模式 中介者模式 备忘录模式 解释器模式 状态模式 10.策略模式 11.责任链模式 ...

qq_43917601的博客 1275

程序员内功心法《设计模式》

灵魂三问 第一问,什么是设计模式? 设计模式是在软件工程实践过程中,JAVA使用者们总结出的良好的编程方法,使用设计模式能够增加系统的健壮性,易修改性和可扩展性,当你进行开发的软件规模比较大的时候,良好的设计模式会给编程带来便利,让系统更加稳定。 第二问,为什么要学习设计模式? 普遍的目的: 1、别人都说要学,别人都说好,所以我要学 2、面试会被问,所以必须学 3、读源码时看到别人在用,不学看不懂源码为什么这样写 4、我刚好看到一套设计模式的视频,嗯老师讲的不错,我想学学 为什么...

优快云学习 2204

如何系统学习设计模式

灵魂三问 第一问, 什么是设计模式? 设计模式是在软件工程实践过程中,JAVA使用者们总结出的良好的编程方法,使用设计模式能够增加系统的健壮性,易修改性和可扩展性,当你进行开发的软件规模比较大的时候,良好的设计模式会给编程带来便利,让系统更加稳定。 第二问,为什么要学习设计模式? 普遍的目的: 别人都说要学,别人都说好,所以我要学 面试会被问,所以必须学 读源码时看到别人在用,不学看不懂源码为什...

yanyuan_1118的专栏 304
上一篇: 努力奋进:一个编程界小菜鸟的心里话
下一篇: 面试官:这年轻人讲的“开闭原则”有那么点东西
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值