里氏替换原则(LSP)由来:

最早是在 妖久八八 年, 由麻神理工学院得一个女士所提出来的。

定义:

1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子型。

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

问题由来:

有一功能P1,由类A完成。现需要将功能P1进行扩展,扩展后的功能为P,其中P由原有功能P1与新功能P2组成。

新功能P由类A的子类B来完成,则子类B在完成新功能P2的同时,有可能会导致原有功能P1发生故障。

解决方案:

当使用继承时,遵循里氏替换原则。类B继承类A时,除添加新的方法完成新增功能P2外,尽量不要重写父类A的方法,也尽量不要重载父类A的方法。

继承包含这样一层含义:

父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。

继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障

举例说明继承的风险,我们需要完成一个两数相减的功能,由类A来负责:

  class Program
{
static void Main(string[] args)
{
B b = new B();
Console.WriteLine("100+20={0}",b.plus(, ));
Console.WriteLine("100-20={0}",b.reduce(, ));
Console.ReadKey();
}
} public class A
{
public int plus(int a, int b)
{
return a + b;
} public int reduce(int a, int b)
{
return a - b;
}
} public class B : A
{
public new int reduce(int a, int b)
{
return a - b + ;
}
}

后来, 我们增加了一个新功能, 要求相减在加上100, 由B类完成该功能。

我们发现原本运行正常的相减功能发生了错误。原因就是类B在给方法起名时无意中重写了父类的方法,造成所有运行相减功能的代码全部调用了类B重写后的方法,

造成原本运行正常的功能出现了错误。在本例中,引用基类A完成的功能,换成子类B之后,发生了异常。

在实际编程中,我们常常会通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,

程序运行出错的几率非常大。如果非要重写父类的方法,比较通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖、聚合,组合等关系代替。

PS: 通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
  • 子类中可以增加自己特有的方法。
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
  • 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

设计模式六大原则(二):里氏替换原则(Liskov Substitution Principle)的更多相关文章

  1. IOS设计模式的六大设计原则之里氏替换原则(LSP,Liskov Substitution Principle)

    定义 里氏替换原则的定义有两种,据说是由麻省理工的一位姓里的女士所提出,因此以其名进行命名. 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换 ...

  2. Java设计模式(4:里氏替换原则和合成复用原则详解

    一.里氏替换原则 如果说实现开闭原则的关键步骤就是抽象化,那么基类(父类)和子类的继承关系就是抽象化的具体实现,所以里氏替换原则就是对实现抽象化的具体步骤的规范.即:子类可以扩展基类(父类)的功能,但 ...

  3. [设计模式]<<设计模式之禅>>关于里氏替换原则

    在面向对象的语言中,继承是必不可少的.非常优秀的语言机制,它有如下优点:● 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性:● 提高代码的重用性:● 子类可以形似父类,但又异于父类,“龙 ...

  4. 设计模式课程 设计模式精讲 3-10 里氏替换原则coding

    1 代码演练 1.1 继承关系判别(是否是真正意义的继承) 1.2 入参控制 1.3 出参控制 1 代码演练 1.1 继承关系判别(是否是真正意义的继承)(其实我觉得这个例子有点牵强) 1.1.1 反 ...

  5. Java设计原则之里氏替换原则

    里氏代换原则由2008年图灵奖得主.美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出.其严格表述如下:如果对每一个类型为S的 ...

  6. 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP

    前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...

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

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

  8. 【C#设计模式】里氏替换原则

    今天,我们再来学习 SOLID 中的"L"对应的原则:里式替换原则. 里氏替换原则 里氏替换原则(Liskov Substitution Principle):派生类(子类)对象能 ...

  9. [OOD]违反里氏替换原则的解决方案

    关于OOD中的里氏替换原则,大家耳熟能祥了,不再展开,可以参考设计模式的六大设计原则之里氏替换原则.这里尝试讨论常常违反的两种形式和解决方案. 违反里氏替换原则的根源是对子类及父类关系不明确.我们在设 ...

  10. C# 实例解释面向对象编程中的里氏替换原则

    在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...

随机推荐

  1. git commit template

    https://www.zhihu.com/question/27462267/answer/204658544 https://gist.github.com/adeekshith/cd4c95a0 ...

  2. ADO.Net数据库帮助类

    public interface IDBHelper { /// <summary> /// 执行sql语句 /// </summary> /// <param name ...

  3. canvas和svg小记

    一.关于canvas <canvas> 是 HTML5 新增的元素,可用于通过使用JavaScript中的脚本来绘制图形 例如,它可以用于绘制图形,创建动画. <canvas> ...

  4. 【Redis发布订阅】

    Redis通过PUBLISH.SUBSCRIBE等命令实现发布与订阅模式. 举例:QQ群的公告,单个发布者,多个收听着. *** 发布/订阅 PUBLISH 频道 消息 将消息发布到指定的频道. . ...

  5. 【Uva 1627】Team them up!

    [Link]: [Description] 给你n个人; 有一些人之间有认识关系 a认识b,b不一定认识a 让你把这n个人分成两组 使得这两组中的每一组: 组内的人与人之间都相互认识. 并且,使得两组 ...

  6. CSUOJ 1635 Restaurant Ratings

    1635: Restaurant Ratings Time Limit: 1 Sec  Memory Limit: 128 MB Description A famous travel web sit ...

  7. window 搭建python环境

    Unofficial Windows Binaries for Python Extension Packages 其中包含大量Windows下的python的module 包含大但不仅限于pip: ...

  8. [Parcel] Bundle a React App with Parcel

    Parcel comes in as the new cool kid in the bundlers world. Unlike other bundlers which take lots of ...

  9. CF 439C(251C题)Devu and Partitioning of the Array

    Devu and Partitioning of the Array time limit per test 1 second memory limit per test 256 megabytes ...

  10. P2P进入整顿期,平衡风险和收益之间的矛盾是关键

        毫无疑问,P2P网贷进入了其诞生以来最为关键的整顿期,随着大量提现困难.跑路的P2P平台被曝光之后.行业对P2P网贷的发展也多了几分慎重.少了几分浮躁.只是,P2P网贷所面临的问题正是其它不论 ...