里氏替换原则(Liskov Substitution Principle,LSP)是面向对象设计(OOD)中比较重要、常见的一种,下面来总结里氏替换原则的知识点,包括:

  • 维基百科定义
    在面向对象的程序设计中,里氏替换原则(Liskov Substitution principle)是对子类型的特别定义。它由芭芭拉·利斯科夫(Barbara Liskov)在1987年在一次会议上名为“数据的抽象与层次”的演说中首先提出。
    里氏替换原则的内容可以描述为: “派生类(子类)对象可以在程式中代替其基类(超类)对象。” 以上内容并非利斯科夫的原文,而是译自罗伯特·马丁(Robert Martin)对原文的解读。其原文为:

芭芭拉·利斯科夫与周以真(Jeannette Wing)在1994年发表论文并提出以上的Liskov代换原则。

SOLID - “SOLID”中的 L 指代了里氏替换原则。
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。

定义2:所有引用基类的地方必须能透明地使用其子类的对象。

里氏代换原则(Liskov Substitution Principle, LSP):所有引用基类(父类)的地方必须能透明地使用其子类的对象。

跟多态还是有点区别的,里氏代换原则说明的是向上转型是安全的(即将子类对象转换成父类对象),只有在确保类型安全的前提下,才能够实现多态。

“里氏代换原则说明的是向上转型是安全的(即将子类对象转换成父类对象),只有在确保类型安全的前提下,才能够实现多态。” 刘老师说的很准确,里氏代换原则确实包含了多态,在里氏替换原则的基础上能设计出更好的多态。

我发表一下看法,作者说的过多的倒像是依赖倒置原则,面向接口编程,我觉得里氏替换原则倒是对继承的定义做了一个清晰的阐述,因为六大设计原则是互相关联的,绝对不应该是什么面向接口编程,我们应该阐述的是里氏替换原则与其他几大原则的不同之处而非共通性。

具体来说,多态是一种面向对象的机制(面向对象三大特性之一),它包括静态多态(函数重载)和动态多态(函数覆盖,或者成为动态绑定),通常是指动态多态,即程序在运行时,子类对象的行为(方法)可以覆盖父类对象的行为(方法)。而里氏代换原则(LSP)是一种面向对象设计原则,任何使用父类的地方都可以使用子类对象,这为开闭原则的实现奠定了基础,使得我们可以针对父类编程,而运行时再确定使用哪个子类对象,从而提高系统的可扩展性和可维护性。在里氏代换原则中,实际上也使用了多态机制,子类对象在覆盖父类对象时,通过多态即可覆盖父类的行为。

里氏代换原则告诉我们,在软件中将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类对象的话,那么它不一定能够使用基类对象。例如:我喜欢动物,那我一定喜欢狗,因为狗是动物的子类;但是我喜欢狗,不能据此断定我喜欢动物,因为我并不喜欢老鼠,虽然它也是动物。

例如有两个类,一个类为BaseClass,另一个是SubClass类,并且SubClass类是BaseClass类的子类,那么一个方法如果可以接受一个BaseClass类型的基类对象base的话,如:method1(base),那么它必然可以接受一个BaseClass类型的子类对象sub,method1(sub)能够正常运行。反过来的代换不成立,如一个方法method2接受BaseClass类型的子类对象sub为参数:method2(sub),那么一般而言不可以有method2(base),除非是重载方法。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象

感觉是这个意思吧,父类已经实现的方便,子类尽量不要去重写,子类可以去实现父类里没有实现的方法?

重写虚方法才会有多态,重写非虚方法对于面向接口编程意义不大,所以理解里氏原则,得以面向接口编程作思考…

JAVA中,多态是不是违背了里氏替换原则??
里氏替换原则要求子类避免重写父类方法,而多态的条件之一却是要求子类重写父类的方法。所以,我搞不懂里氏替换原则与继承,多态之间的关系。求大神解答,初学小弟跪拜。

LSP的原定义比较复杂,我们一般对里氏替换原则 LSP的解释为:子类对象能够替换父类对象,而程序逻辑不变。里氏替换原则有至少以下两种含义:

里氏替换原则是针对继承而言的,如果继承是为了实现代码重用,也就是为了共享方法,那么共享的父类方法就应该保持不变,不能被子类重新定义。子类只能通过新添加方法来扩展功能,父类和子类都可以实例化,而子类继承的方法和父类是一样的,父类调用方法的地方,子类也可以调用同一个继承得来的,逻辑和父类一致的方法,这时用子类对象将父类对象替换掉时,当然逻辑一致,相安无事。
如果继承的目的是为了多态,而多态的前提就是子类覆盖并重新定义父类的方法,为了符合LSP,我们应该将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,当父类是抽象类时,父类就是不能实例化,所以也不存在可实例化的父类对象在程序里。也就不存在子类替换父类实例(根本不存在父类实例了)时逻辑不一致的可能。
不符合LSP的最常见的情况是,父类和子类都是可实例化的非抽象类,且父类的方法被子类重新定义,这一类的实现继承会造成父类和子类间的强耦合,也就是实际上并不相关的属性和方法牵强附会在一起,不利于程序扩展和维护。

如何符合LSP?总结一句话 —— 就是尽量不要从可实例化的父类中继承,而是要使用基于抽象类和接口的继承。

说的很透彻了。说白了,就是大家都基于抽象去编程,而不要基于具体。这样也就可以实现:对扩展(基于抽象)是开放的,对变更(基于具体)是禁止的。

里氏转换原则要求子类从抽象继承而不是从具体继承,如果从抽象继承,子类必然要重写父类方法。因此里氏转换原则和多态是相辅相成的!至于你说的第一条没有听说过。

刚才看了几篇文章,作者说的是,里氏转换原则要避免重写父类的非抽象方法,而多态的实现是通过重写抽象方法实现的,所以并不冲突。

不违反里氏替换的多态:重写父类的抽象方法

其核心思想是:子类必须能够替换其基类。这一思想体现为对继承机制的约束规范,只有子类能够替换基类时,才能保证系统在运行期内识别子类,这是保证继承复用的基础。在父类和子类的具体行为中,必须严格把握继承层次中的关系和特征,将基类替换为子类,程序的行为不会发生任何变化。同时,这一约束反过来则是不成立的,子类可以替换基类,但是基类不一定能替换子类。
Liskov替换原则,主要着眼于对抽象和多态建立在继承的基础上,因此只有遵循了Liskov替换原则,才能保证继承复用是可靠地。实现的方法是面向接口编程:将公共部分抽象为基类接口或抽象类,通过Extract Abstract Class,在子类中通过覆写父类的方法实现新的方式支持同样的职责。
Liskov替换原则是关于继承机制的设计原则,违反了Liskov替换原则就必然导致违反开放封闭原则。
Liskov替换原则能够保证系统具有良好的拓展性,同时实现基于多态的抽象机制,能够减少代码冗余,避免运行期的类型判别。

可能是最好的设计模式入门教程——里氏替换原则相关推荐

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

    里氏替换原则--举例说明Java设计模式中的里氏替换原则 1. 前言 官方定义: 2. 举例说明 2.1 例子介绍 2.2 反例 2.2.1 类图说明 2.2.2 代码说明 2.2.3 测试 2.2. ...

  2. java设计模式3,里氏替换原则

    目录 一.里氏替换原则定义 二.里氏替换原则的作用 三.违背原则场景 四.里氏替换原则改变代码 1.抽象人物类 2.哪吒子类 3.敖丙子类 五.关注公众号哪吒编程,回复1024,获取Java学习资料, ...

  3. 设计模式|LSP(里氏替换)原则

    软件质量保障 专注测试圈,自动化测试.测试平台开发.测试新技术.大厂测试岗面经分享, 可以帮忙内推BATJ等大厂!欢迎加VX沟通交流: ISTE1024 在面向对象的语言中,继承是非常优秀的语言机制, ...

  4. java里氏替换原则例子_java设计模式学习笔记——里氏替换原则

    oo中的继承性的思考和说明 1.继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些七月,但是如果子类对这些已经实现的方法任意修改,就会对 ...

  5. 北风设计模式课程---里氏替换原则(Liskov Substitution Principle)

    北风设计模式课程---里氏替换原则(Liskov Substitution Principle) 一.总结 一句话总结: 当衍生类能够完全替代它们的基类时:(Liskov Substitution P ...

  6. 《设计模式》杂记之里氏替换原则

    在这篇博文中,我想把自己学习过的里氏替换原则一些好知识点分享给大家.首先我想把继承的一下优缺点给大家分享一下,然后再引出里氏替换原则吧!<?xml:namespace prefix = o ns ...

  7. 设计模式 里氏替换原则

    设计模式 里氏替换原则 继续里氏替换原则. 上回栗子为正方形不能被长方形继承,这次,具体 子类必须实现父类的方法 类图 对具体代码进行实践 // 定义抽象类枪 public abstract clas ...

  8. 设计模式-里氏替换原则

    设计模式-里氏替换原则 优点 面向对象的语言继承必不可少的,有如下优点 代码共享,减少创建类的工作量 提高代码的重用性 提高代码的可扩展性 提高代码的可扩展性 提高产品代码的开放性 继承侵入性 只要继 ...

  9. 设计模式六大原则之里氏替换原则、依赖倒置原则详解

    设计模式六大原则--里氏替换原则.依赖倒置原则详解 1.里氏代换原则(Liskov Substitution Principle) 概念 顾名思义,该原则用于经常发生替换的地方,在Java中指的是实现 ...

最新文章

  1. 安装Properties Editor插件,解决XXX.properties文件中文乱码的问题
  2. Caffe官方教程翻译(10):Editing model parameters
  3. SQL注入详解和简单绕过原理
  4. pythonfor循环100次_在for循环中只打印一次
  5. 【UOJ 92】有向图的强连通分量
  6. WS-*协议栈及相关概念
  7. @程序员,CSDN卫衣、背包、鼠标垫......福利来啦!!!
  8. 计算机组成原理-面试题
  9. RS485协议和Modbus协议有什么区别?工业网关能用吗?
  10. 40个好用的Unity游戏开发插件大合集
  11. 移动警务整体解决方案_辅助或替代人类的技术无法解决警务问题
  12. MyBatis Generator生成代码的几种方式
  13. 代码随想录第四天 leetcode 24、19、206
  14. 华为b199usb计算机连接,华为B199如何打开USB调试的方法
  15. 【蓝桥杯单片机国赛 第九届】
  16. 使用pyhton采用多线程方式ping IP
  17. 把Kingston优盘做成USB-CDROM启动盘
  18. 心路历程(一)--天圆地方的时候
  19. 学计算机手机必备软件,精选推荐:手机电脑里的11类值得分享的“神器”,囊括你工作学习以及生活的方方面面...
  20. matlab 环形检测,用matlab模拟环形磁铁的磁场分布详解.doc

热门文章

  1. 侦听器watch及其和计算属性、methods方法的总结
  2. 软件测试基础逻辑思维与理论
  3. 怎么给手机照片添加文字?没想到方法这么容易,1分钟就能学会
  4. Feature Selective Anchor-Free(FSAF)
  5. 【Python】列表生成式应用的八重境界
  6. arcgis注记详解
  7. 2010年下半年卷烟品牌目录
  8. 无背景图片添加白色背景
  9. Warning: Accessing non-existent property ‘cat‘ of module exports inside circular dependency
  10. 用JavaScript技术实现弹幕效果