当前位置: 首页 > news >正文

LSP里氏替换原则

LSP强调子类必须能够替换父类。即子类应该具有与父类相同的行为和功能,而不仅仅是继承父类的属性和方法。LSP是对继承机制的约束规范、是指导接口与实现的设计原则。

LSP关键点

  • 前置条件不能强化:子类方法的参数类型必须与父类相同或者更为宽松
  • 后置条件不能弱化:子类方法的返回值类型必须与父类相同或者是其子类型
  • 不变量要保持:子类不能破坏父类原有的约束条件。
  • 异常类型需兼容:子类方法抛出的异常必须是父类方法抛出异常的子类型。

示例代码

不符合LSP的代码

class Shape {  void draw() {  System.out.println("Drawing a shape");  }  
}
class Circle extends Shape {void draw() {System.out.println("Drawing a circle");  }
}

使用LSP优化后的代码

interface Drawable {  void draw();  
}  
class Shape implements Drawable {  public void draw() {  System.out.println( "Drawing a shape");  }  
}  
class Circle extends Shape {  public void draw() {  System.out.println("Drawing a circle");  }  
}

注意点

子类与父类具有一致的行为和功能:子类必须具有与父类相同的行为和功能,且不能改变父类的行为和功能。

避免继承滥用:避免通过继承来共享行为,继承是用来实现多态,而不是为了代码的重用。如果子类需要不同的功能和行为,那应该通过重写父类方法来实现。

多态与里氏替换原则

多态是实现里氏替换原则的技术手段

多态借助继承和方法重写,让子类对象能够替代父类对象使用。而里氏替换原则要求子类在替换父类时,不能改变程序原有的正确性。所以,多态为里氏替换原则提供了具体的实现方式。

举个例子,有一个抽象类 Shape定义了 area()方法,Rectangle和Circle作为它的子类分别对该方法进行了实现。在使用时,我们可以编写通用代码来处理Shape对象,这就是多态的体现,同时遵循了里氏替换原则。

多态是里氏替换原则的外在表现形式,它通过动态调用子类方法,实现了程序的灵活性和可扩展性。

里氏替换原则是对多态的约束和规范

多态的实现需要遵循一定规则,不然就可能引发问题。里氏替换原则明确了子类在行为上必须与父类保持兼容。要是违背了里氏替换规则,在运行时就可能出现意外情况。比如,子类重写方法时抛出了父类没有声明的异常,那么调用该方法的代码就可能无法正常处理。

里氏替换原则是多态的内在约束,它确保了子类对象能够无缝替换父类对象,从而为多态的实现提供了可靠的语义基础。

两者侧重点不同

  • 多态:关注代码的实现机制,核心在于 “同一接口,多种实现”,目的是提高代码的灵活性。
  • 里氏替换原则:重点在于设计层面,强调子类和父类之间的行为兼容性,目的是保证系统的稳定性。

共同服务于面向对象设计

里氏替换原则和多态都遵循开闭原则,也就是对扩展开放、对修改关闭。多态通过接口抽象来实现功能扩展,而里氏替换原则确保扩展不会破坏已有的系统。

参考

《架构整洁之道》-- Robert C.Mattin

《架构师的自我修炼》 – 李智慧

《设计模式之美》 – 王争

http://www.xdnf.cn/news/375121.html

相关文章:

  • tmux + ttyd 原理
  • FHE 之 面向小白的引导(Bootstrapping)
  • ISP(Image Signal Processor)处理流程及不同域划分
  • 初等数论--莫比乌斯函数
  • STM32硬件I2C驱动OLED屏幕
  • [文献阅读] wav2vec: Unsupervised Pre-training for Speech Recognition
  • 优选算法——队列+BFS
  • Spark的三种部署模式及其特点与区别
  • GitHub 趋势日报 (2025年05月09日)
  • HTTP:十三.HTTP日志
  • 如何解决 PowerShell 显示 “此系统上禁用了脚本运行” 的问题
  • DAMA语境关系图汇总及考前须知
  • 【Linux系统编程】进程属性--进程状态
  • Vision Transformer(ViT)
  • 事务连接池
  • 编写第一个MCP Server之Hello world
  • 【动态导通电阻】软硬开关下GaN器件的动态RDSON
  • 养生:拥抱健康生活的秘诀
  • 深入解析JavaScript变量作用域:var、let、const全攻略
  • React Hooks:从“这什么鬼“到“真香“的奇幻之旅
  • 《基于人工智能的智能客服系统:技术与实践》
  • 二分类问题sigmoid+二元交叉熵损失
  • 微服务的“迷宫” - 我们为何需要服务网格?
  • 数据库故障排查指南:从连接问题和性能优化
  • Docker使用小结
  • 为什么选择 FastAPI、React 和 MongoDB?
  • vue 组件函数式调用实战:以身份验证弹窗为例
  • 计算机大类专业数据结构下半期实验练习题
  • 【基础IO下】磁盘/软硬链接/动静态库
  • 精品,第21章 Python数据类型详解:字典的入门与进阶总结(DevOps SRE视角)