1. 背景

有一个功能p1,由类A完成,现在需要将功能p1进行扩展,扩展后的功能为p3,p3由原功能p1和新功能p2组成,而新功能p3和p2均由类A的子类B来完成,子类B在完成新功能p2的同时,可能会导致原有的功能p1故障。

2. 定义

    所有引用基类的地方能透明的使用其子类对象进行替代。

3. 对应的解决方案

  使用继承时,父类已经实现好了的方法(非抽象方法),实际上是有一系列规范和契约的,虽然不强制子类必须遵循,但如果子类对这些非抽象方法进行重写、重载后,会造成整个继承体系被破坏。而里氏替换原则也正是表达了这层含义。

4. 补充对继承的理解

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

5.  案例

    需求一:完成两个数相减的功能,由类A完成。

  public class A
{
/// <summary>
/// 两数相加
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public int func1(int a, int b)
{
return a - b;
}
/// <summary>
/// 两数相乘
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public int func3(int a, int b)
{
return a * b;
}
}

需求二:完成两个数相加,然后再加100的功能,由类A的子类类B完成。

   public class B:A
{
public int func1(int a, int b)
{
return a + b;
}
public int func2(int a, int b)
{
return func1(a, b) + ;
}
}

 下面我们对上述写的代码进行测试。

(1). 用类A测试两个数相减,如:100-50

(2). 用类B测试两个数相减(因为类B继承了类A),如:100-50

(3). 用类B测试两个数相加后再加100的功能,如:100+50+100

         public static void show()
{
//需求1:完成两个数相减的功能,由类A来完成
A a = new A();
Console.WriteLine("100-50={0}", a.func1(, )); //50 //需求2:完成两个数相加功能,然后再加100,由类A的子类B来完成
B b = new B();
Console.WriteLine("100-50={0}", b.func1(, )); //150,因为子类重写了fun1,则隐藏了父类中fun1原有的方法 (错误)
Console.WriteLine("100和50相加,然后再减掉100,结果为:{0}", b.func2(, )); // }

 结果:

 我们会发现, 用类B测试两个数相减的功能出错了,竟然变成两数相加的功能了,原因是类B中声明了和其父类相同的方法名的方法,即隐藏了父类原有的方法,违背了里氏替换原则。

6. 里氏替换原则的深刻理解

 子类可以扩展父类没有的功能,但是不能改变父类的功能

a:子类可以实现父类的抽象方法,但不能重写父类的非抽象方法。

b:子类可以增加自己特有的方法。

c:子类重载父类方法时,其方法的形参要比父类方法的形参更宽松。

d:子类实现父类抽象方法时,其方法的返回值要比父类方法的更严格。

7. 正宗的里氏替换原则的用法

        public static void show()
{ A aa = new B();
Console.WriteLine("100*50={0}",aa.func3(, )); //5000 正宗的里氏替换原则
//Console.WriteLine(aa.func2(100, 50)); //代码报错,父类不能调用子类扩展的方法
}

8. 违背里氏替换原则的后果

 出错率会增高

02-里氏替换原则(LSP)的更多相关文章

  1. .net学习之继承、里氏替换原则LSP、虚方法、多态、抽象类、Equals方法、接口、装箱拆箱、字符串

    1.继承(1)创建子类对象的时候,在子类对象中会为子类对象的字段开辟空间,也会为父类的所有字段开辟空间,只不过父类私有的成员访问不到(2)子类从父类继承父类所有的非私有成员,但是父类的所有字段也会创建 ...

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

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

  3. 里氏替换原则(LSP)

    替换原则由MIT计算机科学实验室的Liskov女士在1987年的OOPSLA大会上的一篇文章中提出,主要阐述有关继承的一些原则,故称里氏替换原则. 2002年,Robert C.Martin出版了一本 ...

  4. 里氏替换原则LSP(继承规范)

    继承的优点: 1.代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性. 2.提高代码的重用性. 3.子类可以形似父类,但又异于父类. 4.提高代码的可扩展性,实现父类的方法就可以“为所欲为” ...

  5. 架构师之路——里氏替换原则LSP

    定义: 如果对每一个对类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有发生变化,那么类型S是类型T的子类型. 内容: 里氏替换原则通 ...

  6. &quot;围观&quot;设计模式(2)--里氏替换原则(LSP,Liskov Substitution Principle)

    在面向对象的程序设计中.里氏替换原则(Liskov Substitution principle)是对子类型的特别定义.它由芭芭拉·利斯科夫(Barbara Liskov)在1987年在一次会议上名为 ...

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

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

  8. 六大设计原则(二)LSP里氏替换原则

    里氏替换原则LSP(Liskov Subsituation Principle) 里氏替换原则定义 所有父类出现的地方可以使用子类替换并不会出现错误或异常,但是反之子类出现的地方不一定能用父类替换. ...

  9. oc之里氏替换原则

    1. 里氏替换原则. LSP 子类对象可以替换父类对象的位置,并且程序的功能不受影响. 为什么? 1). 指针是1个父类类型,但是我们确给了指针1个子类对象的地址. 这样做当然是可以的,因为你要1个父 ...

  10. 设计模式六大原则(二):里氏替换原则(Liskov Substitution Principle)

    里氏替换原则(LSP)由来: 最早是在 妖久八八 年, 由麻神理工学院得一个女士所提出来的. 定义: 1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 ...

随机推荐

  1. Jquery ajax 表单.serialize() 和serializeArray()序列化$.param()

    .serialize() 方法创建以标准 URL 编码表示的文本字符串.它的操作对象是代表表单元素集合的 jQuery 对象. 表单元素有几种类型: <form> <div>& ...

  2. 转《Angular4项目部署到服务器上刷新404解决办法》

    刚遇到Angular4项目npm run build 后部署到服务器可以访问,但是刷新页面会出现404的错误!转载一大神的操作 解决angular2页面刷新后报404错误办法: 配置app.modul ...

  3. 周刷题第一期总结(two sum and two numbers)

    由于深深的知道自己是事件驱动型的人,一直想补强自己的薄弱环节算法,却完全不知道从哪里入手.所以只能采用最笨的办法,刷题.从刷题中遇到问题就解决问题,最后可能多多少少也能提高一下自己的渣算法吧. 暂时的 ...

  4. SpringBoot(十六)_springboot整合JasperReport6.6.0

    现在项目上要求实现套打,结果公司里有个人建议用JaperReport进行实现,就进入这个东西的坑中.好歹经过挣扎现在已经脱离此坑中.现在我也是仅能实现读取数据库数据转成pdf进行展示,包括中文的展示. ...

  5. Bootstrap滚动监控器

    前面的话 滚动监听插件是用来根据滚动条所处的位置来自动更新导航项的.滚动导航条下面的区域并关注导航项的变化,下拉菜单中的条目也会自动高亮显示.本文将详细介绍Bootstrap滚动监控器 基本用法 滚动 ...

  6. BZOJ4998星球联盟——LCT+并查集(LCT动态维护边双连通分量)

    题目描述 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成 联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两 ...

  7. KEYENCE Programming Contest 2019 自闭记

    A:签到. #include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> ...

  8. 【Linux】Centos6.8下一键安装Lamp环境

    [下载地址] 以下三种都是快捷安装环境的工具,都提供相应的脚本,原理都相同,一个会了其他的也就都会了,我用的比较多的会是lnmp和oneinstack,最近在用的都是oneinstack,挺好用的. ...

  9. 分数拆分(Fractions Again?!, UVa 10976)

    题目链接:https://vjudge.net/problem/UVA-10976 It is easy to see that for every fraction in the form 1k(k ...

  10. CDQZ多校集训记

    20171218 DAY0 初相逢 今天的阳光很好,确实好极了.下午开始时,mercer说门外站了一堆人,我看都不用看就知道是衡水的.衡水人,怎么说呢,觉得还是挺不一样的.不知道像凡哥和超哥这种奇异的 ...