设计模式六大原则(2):里氏替换原则(Liskov Substitution Principle)
肯定有不少人跟我刚看到这项原则的时候一样,对这个原则的名字充满疑惑。事实上原因就是这项原则最早是在1988年,由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的。
定义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来负责。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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
后来,我们须要添加一个新的功能:完毕两数相加,然后再与100求和,由类B来负责。即类B须要完毕两个功能:
- 两数相减。
- 两数相加,然后再加100。
因为类A已经实现了第一个功能,所以类B继承类A后,仅仅须要再完毕第二个功能就能够了,代码例如以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
classBextendsA{
publicintfunc1(inta,intb){
returna+b;
}
publicintfunc2(inta,intb){
returnfunc1(a,b)+100;
}
}
publicclassClient{
publicstaticvoidmain(String[]args){
Bb=newB();
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));
}
}
|
类B完毕后,执行结果:
100-50=150
100-80=180
100+20+100=220
我们发现原本执行正常的相减功能发生了错误。原因就是类B在给方法起名时无意中重写了父类的方法,造成所有执行相减功能的代码所有调用了类B重写后的方法。造成原本执行正常的功能出现了错误。在本例中,引用基类A完毕的功能。换成子类B之后,发生了异常。
在实际编程中,我们经常会通过重写父类的方法来完毕新的功能,这样写起来尽管简单。可是整个继承体系的可复用性会比較差,特别是运用多态比較频繁时,程序执行出错的几率很大。假设非要重写父类的方法,比較通用的做法是:原来的父类和子类都继承一个更通俗的基类,原有的继承关系去掉,採用依赖、聚合,组合等关系取代。
里氏替换原则通俗的来讲就是:子类能够扩展父类的功能。但不能改变父类原有的功能。它包括下面4层含义:
- 子类能够实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中能够添加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形參)要比父类方法的输入參数更宽松。
- 当子类的方法实现父类的抽象方法时。方法的后置条件(即方法的返回值)要比父类更严格。
看上去非常不可思议,由于我们会发如今自己编程中经常会违反里氏替换原则,程序照样跑的好好的。
所以大家都会产生这种疑问,假如我非要不遵循里氏替换原则会有什么后果?
后果就是:你写的代码出问题的几率将会大大添加。
设计模式六大原则(2):里氏替换原则(Liskov Substitution Principle)的更多相关文章
- IOS设计模式的六大设计原则之里氏替换原则(LSP,Liskov Substitution Principle)
定义 里氏替换原则的定义有两种,据说是由麻省理工的一位姓里的女士所提出,因此以其名进行命名. 定义1:如果对一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1所定义的程序P中在o1全都替换 ...
- Java设计模式(4:里氏替换原则和合成复用原则详解
一.里氏替换原则 如果说实现开闭原则的关键步骤就是抽象化,那么基类(父类)和子类的继承关系就是抽象化的具体实现,所以里氏替换原则就是对实现抽象化的具体步骤的规范.即:子类可以扩展基类(父类)的功能,但 ...
- [设计模式]<<设计模式之禅>>关于里氏替换原则
在面向对象的语言中,继承是必不可少的.非常优秀的语言机制,它有如下优点:● 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性:● 提高代码的重用性:● 子类可以形似父类,但又异于父类,“龙 ...
- 设计模式课程 设计模式精讲 3-10 里氏替换原则coding
1 代码演练 1.1 继承关系判别(是否是真正意义的继承) 1.2 入参控制 1.3 出参控制 1 代码演练 1.1 继承关系判别(是否是真正意义的继承)(其实我觉得这个例子有点牵强) 1.1.1 反 ...
- Java设计原则之里氏替换原则
里氏代换原则由2008年图灵奖得主.美国第一位计算机科学女博士Barbara Liskov教授和卡内基·梅隆大学Jeannette Wing教授于1994年提出.其严格表述如下:如果对每一个类型为S的 ...
- 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
前言 本章我们要讲解的是S.O.L.I.D五大原则JavaScript语言实现的第3篇,里氏替换原则LSP(The Liskov Substitution Principle ). 英文原文:http ...
- 北风设计模式课程---里氏替换原则(Liskov Substitution Principle)
北风设计模式课程---里氏替换原则(Liskov Substitution Principle) 一.总结 一句话总结: 当衍生类能够完全替代它们的基类时:(Liskov Substitution P ...
- 【C#设计模式】里氏替换原则
今天,我们再来学习 SOLID 中的"L"对应的原则:里式替换原则. 里氏替换原则 里氏替换原则(Liskov Substitution Principle):派生类(子类)对象能 ...
- [OOD]违反里氏替换原则的解决方案
关于OOD中的里氏替换原则,大家耳熟能祥了,不再展开,可以参考设计模式的六大设计原则之里氏替换原则.这里尝试讨论常常违反的两种形式和解决方案. 违反里氏替换原则的根源是对子类及父类关系不明确.我们在设 ...
- C# 实例解释面向对象编程中的里氏替换原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
随机推荐
- CodeForces 486C Palindrome Transformation 贪心+抽象问题本质
题目:戳我 题意:给定长度为n的字符串,给定初始光标位置p,支持4种操作,left,right移动光标指向,up,down,改变当前光标指向的字符,输出最少的操作使得字符串为回文. 分析:只关注字符串 ...
- BZOJ 2134: 单选错位( 期望 )
第i个填到第i+1个的期望得分显然是1/max(a[i],a[i+1]).根据期望的线性性, 我们只需将每个选项的期望值累加即可. ---------------------------------- ...
- ContentProvider中的数据生成时机
目录结构: , 先给个结论: 仅仅是实例化mySqliteHelper()这个类的时候是不会创建数据库的,实际上数据库的真正创建是在helper.getWritableDatabase()的方法执行后 ...
- 一个开源Delphi分类组件推荐网页
https://github.com/Fr0sT-Brutal/awesome-delphi
- 180China丨the Agency for Brand Engagement and Experience
180China丨the Agency for Brand Engagement and Experience Welcome to 180. Welcome to Creativity. Thank ...
- Entity Framework基金会
概要 Entity Framework缩写EF,微软ORM产品. 本篇博客将简单的介绍它,至于它的详细深层次的使用,大家能够查询对应的操作手冊,该篇不过入门. Entity Framework和Lin ...
- IOS 获取网络图像尺寸 更改 图像色彩值 什么一套方法灰色
直接在代码 头文件 // 图片处理 0 半灰色 1 灰度 2 深棕色 3 反色 +(UIImage*)imageWithImage:(UIImage*)image grayLevelType:(UII ...
- IOS的处理touch事件处理(按照手指的移动移动一个圆,开发环境用的ios7,storyboard)
先看下页面的效果图: 首先定义这个ball它有两个属性和两个方法: @property(nonatomic) CGPoint location; @property(nonatomic) CGFloa ...
- BZOJ 2212: [Poi2011]Tree Rotations( 线段树 )
线段树的合并..对于一个点x, 我们只需考虑是否需要交换左右儿子, 递归处理左右儿子. #include<bits/stdc++.h> using namespace std; #defi ...
- CentOS6.5 配置防火墙+允许指定ip访问端口
参考博文: iptables防火墙只允许指定ip连接指定端口.访问指定网站 一.配置防火墙 打开配置文件 [root@localhost ~]# vi /etc/sysconfig/iptables ...