1.全称

  • liskov substitution principle
  • 缩写为:LSP

2.解释

  • 继承必须确保超类所拥有的性质在子类中仍然成立
  • 里氏替换原则主要阐述了有关继承的一些原则,也就是什么时候应该使用继承,什么时候不应该使用继承,以及其中蕴含的原理。
  • 里氏替换原是继承复用的基础,它反映了基类与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范

3.里氏替换原则的实现方法

  • 1.里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法

  • 2.类的继承原则:里氏替换原则常用来检查两个类是否为继承关系。在符合里氏替换原则的继承关系中,使用父类代码的地方,用子类代码替换后,能够正确的执行动作处理。换句话说,如果子类替换了父类后,不能够正确执行动作,那么他们的继承关系就是不正确的,应该重新设计它们之间的关系。

    class zhangsan:def sing(self):print(f"张三唱歌五音不全.")class zhangsanson(zhangsan):def dance(self):print("张三儿子会跳舞")if __name__ == "__main__":zs = zhangsan()zs_son = zhangsanson()# 调用张三唱歌的方法zs.sing()# 替换为张三儿子来调用依然可以,没有任何变化,说明符合继承zs_son.sing()
    
  • 3.动作正确性保证:里氏替换原则对子类进行了约束,所以在为已存在的类进行扩展,来创建一个新的子类时,符合里氏替换原则的扩展不会给已有的系统引入新的错误。符合开闭原则

  • 4.如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

  • 5.如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。

1.场景:正方形不是长方形

class Rectangle:def __init__(self, width, height):self._width = widthself._height = height@propertydef width(self):return self._width@width.setterdef width(self, value):self._width = value@propertydef height(self):return self._height@height.setterdef height(self, value):self._height = value@propertydef area(self):return self._height * self._widthdef __str__(self):return f"Width: {self.width}, Height: {self.height}"class Square(Rectangle):def __init__(self, size):super().__init__(width=size, height=size)@Rectangle.width.setterdef width(self, value):self._width = valueself._height = value@Rectangle.width.setterdef height(self, value):self._height = valueself._width = valuedef use_it(rc):w = rc.widthrc.height = 10  # 修改宽为10expected = w * 10print(f"Expected an area of {expected}, got {rc.area}")if __name__ == '__main__':#rc = Rectangle(15, 5)# # Expected an area of 150, got 150use_it(rc)# 正方形的长和宽是一致的,所以只需要设置一个值即可sq = Square(15)# Expected an area of 50, got 100use_it(sq)

2.结论

  • 父类Rectangle不能被子类Square替换,如果进行了替换就得不到预期结果。因此,Square类和Rectangle类之间的继承关系违反了里氏替换原则,它们之间的继承关系不成立,正方形不是长方形。

3.阐释

正方形不是长方形正方形是长方形也不是长方形,这样结论似乎就是个悖论。产生这种混乱的原因有两个:
  • 原因一:对类的继承关系的定义没有搞清楚。

    • 面向对象的设计关注的是对象的行为,它是使用“行为”来对对象进行分类的,只有行为一致的对象才能抽象出一个类来

    正方形在设置长度和宽度这两个行为上,与长方形显然是不同的

    长方形的行为:设置长方形的长度的时候,它的宽度保持不变,设置宽度的时候,长度保持不变

    正方形的行为:设置正方形的长度的时候,宽度随之改变;设置宽度的时候,长度随之改变。

    所以,如果我们把这种行为加到父类长方形的时候,就导致了正方形无法继承这种行为。我们“强行”把正方形从长方形继承过来,就造成无法达到预期的结果。

  • 原因二:设计要依赖于用户需求和具体环境。

    • 继承关系要求子类要具有基类全部的行为。这里的行为是指落在需求范围内的行为
    • 所有子类的行为功能必须和使用者对其父类的期望保持一致,如果子类达不到这一点,那么必然违反里氏替换原则
    • 比如鸵鸟和鸟:鸵鸟是否可以继承自鸟
      • 需求一:用户关注点是飞行,由于鸵鸟不会飞,所以此时来看就不符合继承关系
      • 需求二:用户关注点是爪子或者羽毛,此时就可以满足继承关系

4.违反里氏替换原则需重新设计关系

1.方式一

  • 创建一个新的抽象类或者接口,作为两个具体类的基类。将具体类A和B的共同行为转移到C中,从而解决A和B行为不一致的问题。

2.方式二

  • 将B到A的继承关系改为委托关系。具体参考组合/聚合复用原则。

3.方式一解决长方形不是正方形问题

  • 正方形和长方形的共同行为(getLength()、getWidth()方法)抽象并封装转移到一个抽象类或者接口中,比如一个“四方形”接口或者抽象类,然后让正方形和长方形分别实现四方形接口或者继承四方形抽象类,如下图所示
  • 一般来说,只要有可能,就不要从具体类继承
  • 所有的继承都是从抽象类开始,而所有的具体类都没有子类。也就是说,在一个由继承关系形成的等级结构中,树叶节点都应当是具体类,树枝节点都应该是抽象类或者接口。

4.里氏替换原则的作用

1.里氏替换原则是实现开闭原则的重要方式之一。

2.它克服了继承中重写父类造成的可复用性变差的缺点。

3.它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。

设计原则——里氏替换原则相关推荐

  1. 设计模式原则—里氏替换原则

    设计模式概念与作用: 设计模式是一套被反复使用的.多数人知晓.经过分类编目的优秀代码设计经验的总结.特定环境下特定问题的处理方法. 1)重用设计和代码 重用设计比重用代码更有意义,自动带来代码重用 2 ...

  2. 软件设计的七大原则 --开闭原则 里氏替换原则 依赖倒置原则

    在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据 7 条原则来开发程序,从而提高软件开发效率.节约软件开发成本和维护成本. 这 7 种设计原则是软件设计 ...

  3. 设计原则(单一职责原则 开放封闭原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则)

    设计原则 单一职责原则(SRP) 从三大特性角度看原则: 应用的设计模式: 开放封闭原则(OCP) 从三大特性角度看原则: 应用的设计模式: 里氏替换原则(LSP) 从三大特性角度看原则: 应用的设计 ...

  4. Java设计原则——里氏替换原则

    我们一定要给自己提出这样的任务:第一,学习,第二是学习,第三还是学习. 学习从来无捷径,循序渐进登高峰. 目录 一.基本介绍 二.应用实例 1.示例一 2.示例二 部分笔记来源于尚硅谷设计模式视频教学 ...

  5. 软件架构设计原则--里氏替换原则

    本专栏内容参考自:咕泡学院Tom老师的<Spring5核心原理与30个类手写实战>,仅作个人学习记录使用,如有侵权,联系速删   里氏替换原则(Liskov Substitution Pr ...

  6. 【设计模式】软件设计七大原则 ( 里氏替换原则 | 定义 | 定义扩展 | 引申 | 意义 | 优点 )

    文章目录 一.里氏替换原则定义 二.里氏替换原则定义扩展 三.里氏替换原则引申意义 四.里氏替换原则意义 五.里氏替换原则优点 一.里氏替换原则定义 里氏替换原则定义 : 如果 对每一个 类型为 T1 ...

  7. 软件架构设计原则-里氏替换原则

    前言 里氏替换原则简单的理解可以是父类用到的地方可以用子类替换并且不改变逻辑,这就要求子类可以扩展父类的功能,但不能改变父类原有的功能.里氏替换原则要求 (1) 子类可以实现父类的抽象方法,但不能覆盖 ...

  8. 设计模式之七大原则——里氏替换原则(LSP)(三)

    里氏替换原则(Liskov Substitution Principel)是解决继承带来的问题. 4 里氏代换原则(Liskov Substitution Principle, LSP) 4.1 什么 ...

  9. 设计模式六大原则:里氏替换原则(五)

    转载请标明:http://blog.csdn.net/liulongling/article/details/51383159 面向对象其它六大原则 单一职责原则-带你走梦幻西游(一) 依赖倒置原则( ...

最新文章

  1. oracle symonym_oracle vs. SQL 同义词synonym 别名 alias | 学步园
  2. plotly可视化绘制多坐标轴图
  3. c++ vector向量直接赋值_vector-Jacobian product 解释 ---- pytorch autograd
  4. 正则表达式在iOS中的运用
  5. 判断是否为质数的超级优化 C++语言(超详细)
  6. SpringBoot中使用异步方法优化Service逻辑,提高接口响应速度
  7. 基于 PostgreSQL 的 EMQ X Auth ACL
  8. koa2异常处理_koa2 中的错误处理以及中间件设计原理
  9. Linux宝库名人轶事栏目 | 笨叔与Linux的那些事(下)
  10. 高质量论文配图配色,让你的图更加亮眼
  11. 单元测试,我有话说(No tests to run. No tests were executed)
  12. 恶补地理知识--四大洋,七大洲
  13. eclipse hana xs 开发环境搭建
  14. 163邮箱 提示xm002 NO SELECT Unsafe Login. Please contact kefu@188.com for help
  15. 网络协议 -- ARP和RARP协议
  16. JAVA数组自动排序
  17. 计算机 无法进入pe,无法进入老毛桃pe系统解决办法[推荐]
  18. 第3章第6节:如何在幻灯片中使用gif动画 [PowerPoint精美幻灯片实战教程]
  19. 【概率DP】 ZOJ 3380 Patchouli's Spell Cards
  20. vue移动端表格吸顶、行自适应高度、列左侧固定悬浮

热门文章

  1. 【Flutter】Android、Flutter 折叠屏适配 ( 展开大屏 | 折叠主屏 | 折叠副屏 | 静态展示 | 动态热切换适配 | 拉伸布局 | X 轴自适应适配 | 布局重构 )
  2. IDEA 抽取变量快捷键失效
  3. 绝地求生北美服务器延迟过高,绝地求生刺激战场网络延迟很高怎么办 绝地求生刺激战场网络延迟很高的解决方法...
  4. maven中的dependencies与dependencyManagement 对依赖管理的区别
  5. html页面左右滑动固定插件,jQuery全屏滚动插件fullPage.js让你的页面分屏滚动
  6. postive psychology
  7. 踏莎行·术 - IM设计思考:试问
  8. 删除卡在C盘和D盘之间的恢复盘
  9. 基于Unreal引擎的大地形加载研究
  10. 阿里巴巴:将积极配合监管部门调查