OOAD-4 面对对象设计七原则--里氏替换原则

里氏替换原则的定义java

  里氏替换原则(Liskov Substitution Principle,LSP)由麻省理工学院计算机科学实验室的里斯科夫(Liskov)女士在 1987 年的“面向对象技术的高峰会议”(OOPSLA)上发表的一篇文章《数据抽象和层次》(Data Abstraction and Hierarchy)里提出来的,她提出:继承必须确保超类所拥有的性质在子类中仍然成立测试

 

里氏替换原则的做用spa

  里氏替换原则是实现开闭原则的重要方式之一。设计

  它克服了继承中重写父类形成的可复用性变差的缺点,由于它推崇,子类能够新增方法,可是不要去覆盖父类已经写好的方法orm

  它是动做正确性的保证,即类的扩展不会给已有的系统引入新的错误。下降了代码出错的可能性。由于里式替换原则保证了子类不要去覆盖父类方法,所以,新增新的子类时。父类定义的东西不会改变。也就是说,进行功能扩展时,原有的代码不会出错对象

 

 

里式替换原则的实现方法blog

  里式替换原则通俗来说就是:子类能够扩展父类的功能,但不能改变父类原有的功能。也就是说,子类继承父类时,除添加新的方法完成新增功能外,尽可能不要重写父类已经实现的方法。继承

  若是经过重写父类的方法来完成新的功能,这样写起来虽然简单,可是整个继承体系的可复用性会比较差,特别是用多态用的比较频繁时,程序出错的几率就会变大。由于子类重写毕竟覆盖了父类的功能,当须要使用父类的功能时,就容易致使出错。并且,里氏替换和多态并不冲突,咱们尽可能在抽象类或者接口来作多态,简单父类通常只是用来自下而上的封装公有域。接口

  若是程序违背了里式替换原则,则继承类的对象在基类出现的地方会出现运行错误。由于子类重写了方法,那么本来为基类的地方就不必定能用子类来代替了ip

 

  下面以“几维鸟不是鸟”为例来讲明里氏替换原则。

【例2】里氏替换原则在“几维鸟不是鸟”实例中的应用。

分析:鸟通常都会飞行,如燕子的飞行速度大概是每小时 120 公里。可是新西兰的几维鸟因为翅膀退化没法飞行。假如要设计一个实例,计算这两种鸟飞行 300 公里要花费的时间。显然,拿燕子来测试这段代码,结果正确,能计算出所须要的时间;但拿几维鸟来测试,结果会发生“除零异常”或是“无穷大”,明显不符合预期,其类图如图 1 所示。

“几维鸟不是鸟”实例的类图
图1 “几维鸟不是鸟”实例的类图


程序代码以下:

  1. package principle;
  2. public class LSPtest
  3. {
  4. public static void main(String[] args)
  5. {
  6. Bird bird1=new Swallow();
  7. Bird bird2=new BrownKiwi();
  8. bird1.setSpeed(120);
  9. bird2.setSpeed(120);
  10. System.out.println("若是飞行300千米:");
  11. try
  12. {
  13. System.out.println("燕子将飞行"+bird1.getFlyTime(300)+"小时.");
  14. System.out.println("几维鸟将飞行"+bird2.getFlyTime(300)+"小时。");
  15. }
  16. catch(Exception err)
  17. {
  18. System.out.println("发生错误了!");
  19. }
  20. }
  21. }
  22. //鸟类
  23. class Bird
  24. {
  25. double flySpeed;
  26. public void setSpeed(double speed)
  27. {
  28. flySpeed=speed;
  29. }
  30. public double getFlyTime(double distance)
  31. {
  32. return(distance/flySpeed);
  33. }
  34. }
  35. //燕子类
  36. class Swallow extends Bird{}
  37. //几维鸟类
  38. class BrownKiwi extends Bird
  39. {
  40. public void setSpeed(double speed)
  41. {
  42. flySpeed=0;
  43. }
  44. }


程序的运行结果以下:

若是飞行300千米:
燕子将飞行2.5小时.
几维鸟将飞行Infinity小时。


程序运行错误的缘由是:几维鸟类重写了鸟类的 setSpeed(double speed) 方法,这违背了里氏替换原则。正确的作法是:取消几维鸟原来的继承关系,定义鸟和几维鸟的更通常的父类,如动物类,它们都有奔跑的能力。几维鸟的飞行速度虽然为 0,但奔跑速度不为 0,能够计算出其奔跑 300 公里所要花费的时间。其类图如图 2 所示。

“几维鸟是动物”实例的类图
图2 “几维鸟是动物”实例的类图
 
  
 
 
里氏替换原则和多态之间的关系
  在第一眼看到里氏替换原则时,我就产生了困惑。为何要去禁止子类重写父类方法呢。这不是java多态的基本吗,那里式替换原则是否是和多态概念有冲突呢。后来在和朋友交流时候慢慢的有了一些感悟。故而记录下来。
   首先在咱们的java语言中。能够用来实现多态的方式有不少种。通常为普通父类、抽象类和接口。而对普通父类而言。它不要用来作多态。普通的父类是自下而上的封装共性域的一种形式。通常而言,咱们封装普通父类,是由于有共有的属性、方法。不须要去重写,而是自下而上的封装共性。所以针对普通父类中定义的方法,其实就是子类的共性方法,原理上若是不是共性的方法,就不能抽象为父类。所以普通父类中定义且实现的方法,子类一律不要去重写。这就能看出来里式替换的原理。而多态通常是在抽象类或者接口层去作的。这是由于。抽象类和接口都是自上而下的定义行为约束。例如在抽象类或者接口中,定义的抽象方法,并没有具体实现,这就是代表子类必需要去重写该方法来实现多态。而针对抽象类或者接口中已经定义且作了实现的方法,则就是共性定义的方法。继承抽象类或者实现接口的类都不该该去覆盖该方法,就直接拿来用就行了。这也是里氏替换原则的体现
相关文章
相关标签/搜索