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的方法。

3.使用特点

  继承包含这样一层含义:父类中凡是已经实现好的方法(相对于抽象方法而言),实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些非抽象方法任意修改,就会对整个继承体系造成破坏。而里氏替换原则就是表达了这一层含义。
  继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。
  里氏替换原则通俗的来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。它包含以下4层含义:
(1)子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
(2)子类中可以增加自己特有的方法。
(3)当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
(4)当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

4.实现案例

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

class A{
public int func1(int a,int b){
return a-b;
}
}
public class Client{
public static void main(string[] args){
A a=new A();
System.out.println("100-50="+a.func1(100,50));
System.out.println("100-80="+a.func1(100,80));
}
}
运行结果:
100-50=50
100-80=20

(2)后来,我们需要增加一个新的功能:完成两数相加,然后再与100求和,由类B来负责。

Class B extends A{
public int func1(int a,int b){
return a+b;
}
public int func2(int a,int b){
return func1(a,b)+100;
}
}
public class Client{
public static void main(string[] args){
B a=new B();
System.out.println("100-50="+b.func1(100,50));
System.out.println("100-80="+b.func1(100,80));
System.out.println("100+20+100="+b.func2(100,20));
}
}
运行结果:
100-50=150
100-80=180
100+20+100=220
  我们发现原来运行正常的相减功能发生了错误。原因就是类B无意中重写了父类的方法,造成原有功能出现错误。在实际编程中,我们常常会通过重写父类的方法完成新的功能,这样写起来虽然简单,但整个继承体系的复用性会比较差。特别是运行多态比较频繁的时候,如果非要重写父类的方法,通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,采用依赖,聚合,组合等关系代替。
 
作者QQ:1095737364    QQ群:123300273     欢迎加入!

设计模式原则(2)--Liskov Substitution Principle(LSP)--里氏替换原则的更多相关文章

  1. 面象对象设计原则之三:里氏替换原则(The Liskov Substitution Principle,LSP)

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

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

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

  3. 里氏替换原则(Liskov Substitution Principle)

    开放封闭原则(Open Closed Principle)是构建可维护性和可重用性代码的基础.它强调设计良好的代码可以不通过修改而扩展,新的功能通过添加新的代码来实现,而不需要更改已有的可工作的代码. ...

  4. 里氏代换原则(Liskov Substitution Principle,LSP)

    第一种定义: 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换为o2,程序P的行为没有发生变化,那么类型S是类型T的子类型. 第二种定义: 所有引 ...

  5. 里氏替换原则(Liskov Substitution Principle) LSP

    using System; using System.Collections.Generic; using System.Text; namespace LiskovSubstitutionPrinc ...

  6. 面向对象设计原则 里氏替换原则(Liskov Substitution Principle)

    里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一. 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现. LSP是继承复用的基石,只 ...

  7. 第2章 面向对象的设计原则(SOLID):2_里氏替换原则(LSP)

    2. 里氏替换原则(Liskov Substitution Principle,LSP) 2.1 定义 (1)所有使用基类的地方必须能透明地使用子类替换,而程序的行为没有任何变化(不会产生运行结果错误 ...

  8. 【设计模式六大原则2】里氏替换原则(Liskov Substitution Principle)

      肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑.其实原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的. 定义1:如果对 ...

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

    肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑.事实上原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的. 定义1:假设对每 ...

随机推荐

  1. Html 学习

    行内元素和块级元素 行内元素(行级元素) 多个元素会在一行内显示 块级元素 独立成行 注意:块级元素能够嵌套行内元素 <div> <span></span> < ...

  2. updateByPrimaryKey和updateByPrimaryKeySelective insert和insertSelective

    这两个update都是使用generator生成的mapper.xml文件中,对dao层的更新操作 updateByPrimaryKey对你注入的字段全部更新(不判断是否为Null) updateBy ...

  3. Unity3D文件读取

    Resources: 是作为一个Unity3D的保留文件夹出现的,也就是如果你新建的文件夹的名字叫Resources,那么里面的内容在打包时都会被无条件的打到发布包中.它的特点简单总结一下就是: 只读 ...

  4. BZOJ3575 HNOI2014 道路阻塞

    3575: [Hnoi2014]道路堵塞 Time Limit: 10 Sec  Memory Limit: 128 MB Description A国有N座城市,依次标为1到N.同时,在这N座城市间 ...

  5. SpringMVC源码情操陶冶-FreeMarker之web配置

    前言:本文不讲解FreeMarkerView视图的相关配置,其配置基本由FreeMarkerViewResolver实现,具体可参考>>>SpringMVC源码情操陶冶-ViewRe ...

  6. 解决mydql执行sql文件时报Error: Unknown storage engine 'InnoDB'的错误。

    我运行了一个innoDB类型的sql文件,报了Error: Unknown storage engine 'InnoDB'错误,网上查了很多方法,但是都没办法真正解决我的问题,后来解决了,在这里总结一 ...

  7. (转)eclipse安装jetty

    背景:在项目开发的过程中,一个老的项目使用的是jetty启动,在用tomcat启动的过程中出现了启动不了的异常,浪费了好多时间.因为项目一直是用jetty启动的,为了不浪费时间,也只好改变思路选择je ...

  8. 浅析python 的import 模块(转)

    摘要: 学习python有几天了,对import一直不是很清楚,和C里面的include是否一样,重复引入有问题么?搜索路径是怎样的?整理解决下我的疑问. 一 模块的搜索路径 模块的搜索路径都放在了s ...

  9. C#委托基础学习

    什么是委托       委托,顾名思义就是在你忙着做另一件事时候,你要去做另一件事,于是你可能就会委托别人帮你做,让别人把结果返回给你.编程时,委托也有这个思想. 我目前对委托的看法是,在编程中,委托 ...

  10. python的__init__几种方法总结

    参考 __init__() 这个方法一般用于初始化一个类 但是 当实例化一个类的时候, __init__并不是第一个被调用的, 第一个被调用的是__new__ #!/usr/bin/env pytho ...