博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式六大原则之里氏替换原则
阅读量:5152 次
发布时间:2019-06-13

本文共 3285 字,大约阅读时间需要 10 分钟。

1 里氏替换原则定义

Liskov于1987年提出了一个关于继承的原则“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“继承必须确保父类所拥有的性质在子类中仍然成立。”也就是说,当一个子类的实例应该能够替换任何其父类的实例时,它们之间才具有is-A关系。该原则称为Liskov Substitution Principle——里氏替换原则。

2 经典案例

2.1 正方形不是长方形

在我们的认知范围内,长方形的长不等于宽,正方形是长等于宽的长方形,正方形是一种特殊的长方形。但在实际编码过程中遇到的情况是怎么样的呢,通过代码分析:
1  public class Rectangle 2     { 3         public virtual  int Width { get; set; } 4         public virtual  int Height{ get; set; } 5         public int Area() 6         { 7             return Width * Height; 8         } 9     }10     public class Square : Rectangle11     {12         public override int Width13         {14             get15             {16                 return base.Width;17             }18             set19             {20                 base.Width = value;21                 base.Height = value;22             }23         }24         public override int Height25         {26             get27             {28                 return base.Height;29             }30             set31             {32                 base.Height = value;33                 base.Width = value;34             }35         }36     }

Square继承Rectangle。按照里氏替换原则原则,只要是父类出现的地方都可以用子类进行替换。

1  public static void TestMethod(Rectangle rec)2         {3             rec.Width = 10;4             rec.Height = 15;5             var area = rec.Area();6             Assert.AreEqual(150, area);7         }

那么该方法中的Rectangle rec是可以替换成Square的。我们试试:

1  static void Main(string[] args)2         {3             Rectangle r = new Rectangle();4             TestMethod(r);5             Square s = new Square();6             TestMethod(s);7         }

运行结果如下:

说明正方形是特殊的长方形违背了里氏替换原则。

2.2 鸵鸟非鸟

根据生物学的定义鸵鸟实实在在是鸟类,有羽毛几乎覆盖全身的卵生脊椎动物,温血卵生,用肺呼吸,几乎全身有羽毛,后肢能行走,前肢变为翅,大多数能飞。定义一个鸟类,定义一个继承鸟类的鸵鸟类。

1 public class Bird 2     { 3         public virtual int FlySpeed{
get;set;} 4 public void Fly() { } 5 } 6 public class Ostrich : Bird 7 { 8 public override int FlySpeed 9 {10 get11 {12 return base.FlySpeed;13 }14 set15 {16 base.FlySpeed = 0;//不会飞 飞不起来17 }18 }19 }

鸵鸟不会飞啊,所以速度为0.

1  class Program 2     { 3         static void Main(string[] args) 4         { 5             Ostrich os = new Ostrich(); 6             var time = CalculationFlyTime(os); 7             Console.ReadKey(); 8         } 9       10         public static double CalculationFlyTime(Bird bird)11         {12             return 100 / bird.FlySpeed;13         }14 15     }

运行程序报错:

3.总结

所谓对象是一组状态和一系列行为的组合。状态是对象的内在特性,行为是对象的外在特性。LSP所表述的就是在同一个继承体系中的对象应该有共同的行为特征。我们在设计对象时是按照行为进行分类的,只有行为一致的对象才能抽象出一个类来。设置长方形的长度的时候,它的宽度保持不变,设置宽度的时候,长度保持不变。正方形的行为:设置正方形的长度的时候,宽度随之改变;设置宽度的时候,长度随之改变。所以,如果我们把这种行为加到基类长方形的时候,就导致了正方形无法继承这种行为。我们“强行”把正方形从长方形继承过来,就造成无法达到预期的结果。鸵鸟非鸟,能飞是鸟的特性,但鸵鸟是不能飞的,我们强行将其归为鸟类,最终导致代码出错。

所有子类的行为功能必须和其父类持一致,如果子类达不到这一点,那么必然违反里氏替换原则。在实际的开发过程中,不正确的派生关系是非常有害的。伴随着软件开发规模的扩大,参与的开发人员也越来越多,每个人都在使用别人提供的组件,也会为别人提供组件。最终,所有人的开发的组件经过层层包装和不断组合,被集成为一个完整的系统。每个开发人员在使用别人的组件时,只需知道组件的对外裸露的接口,那就是它全部行为的集合,至于内部到底是怎么实现的,无法知道,也无须知道。所以,对于使用者而言,它只能通过接口实现自己的预期,如果组件接口提供的行为与使用者的预期不符,错误便产生了。里氏替换原则就是在设计时避免出现派生类与基类不一致的行为。

 

转载于:https://www.cnblogs.com/smilejeffery/p/6813468.html

你可能感兴趣的文章
面试整理:Python基础
查看>>
Python核心编程——多线程threading和队列
查看>>
Program exited with code **** 相关解释
查看>>
装服务器,测试数据库,简单的maven命令
查看>>
升级Firefox8后watir-webdriver出现错误“unable to obtain stable firefox connection in 60 seconds”...
查看>>
第6章 Overlapped I/O, 在你身后变戏法 ---被激发的 Event 对象 -4
查看>>
植物大战僵尸中文年度版
查看>>
26、linux 几个C函数,nanosleep,lstat,unlink
查看>>
001.RAID简介
查看>>
投标项目的脚本练习2
查看>>
第五次实验
查看>>
201521123107 《Java程序设计》第9周学习总结
查看>>
runtime的基本应用
查看>>
关于scrollTop的那些事
查看>>
Caroline--chochukmo
查看>>
算法导论笔记 第8章 线性时间排序
查看>>
利用jquery的contains实现搜索功能
查看>>
Xcode 6.2 beta 3 太难下载!下载了,不敢独享
查看>>
并发编程
查看>>
Bootstrap
查看>>