里氏替换原则详解(定义特点及经典示例)

里氏替换原则详解(定义特点及经典示例)-mikechen

里氏替换原则定义

里式替换原则,英文名Liskov Substitution Principle 简称LSP,由麻省理工学院计算机科学实验室的Liskov女士提出来的。

提出来的大意就是:所有引用基类的地方必须能透明地引用其子类的对象,即子类可以拓展父类的功能,但不能修改父类已有的功能。

里氏替换原则详解(定义特点及经典示例)-mikechen

里氏替换原则是面向对象设计的基本原则,是继承复用的基石。

 

里氏替换原则约束

如果要符合里氏替换原则的设计,大致需要满足如下约束。

简要分为5大约束:

  • 第一:子类对象可以完全替代父类对象;
  • 第二:应把基类设计成抽象类而非具象类,应从抽象类派生子类,而不应从具象类继承;
  • 第三:子类应该实现父类的抽象方法,而不应该重写父类的已实现方法;
  • 第四:子类可以扩充新的功能,而不应该改变父类已有的功能;
  • 第五:子类不能增添任何父类没有的附加约束;

 

里氏替换原则经典示例

接下来通过代码的方式举例说明,看个里氏替换原则经典示例:《鸵鸟不是鸟》,更容易理解里氏替换原则。

首先,我们看下生物学中对于鸟类的定义,这样好抽象设计鸟类。

鸟的定义:恒温动物 卵生,全身披有羽毛 身体呈流线形,前肢退化成翼有四趾。

大多数的鸟类在人们的印象中都是会飞的,所以我们给鸟类设计了一个名字为fly的方法,还给出了与飞行相关的一些属性等。

1.设计鸟类Bird

class Bird {
    double velocity;

    public void fly() { //I am flying;
    }

    public void setVelocity(double velocity) {
        this.velocity = velocity;
    }

    public double getVelocity() {
        return this.velocity;
    }
}

 

2.设计鸵鸟类Ostrich

从生物学角度来看,鸵鸟肯定是一种鸟。

我们设计一个与鸟有关的系统,鸵鸟类顺理成章地由鸟类派生,鸟类所有的特性和行为都被鸵鸟类继承。

class Ostrich extends Bird {
    public void fly() {
        //I do nothing; 
    }

    public void setVelocity(double velocity) {
        this.velocity = 0;
    }

    public double getVelocity() {
        return 0;
    }
}

 

3.测试类TestBird

好了,所有的类都设计完成了,我们来测试下。

class TestBird {
   public calcFlyTime(Bird bird) {
   try{
     double riverWidth = 3000;
     System.out.println(riverWidth / bird.getVelocity());
   }catch(Exception err){
     System.out.println("An error occured!");
   }
   };
}

如果我们拿一种飞鸟来测试这段代码,没有问题,结果正确,符合我们的预期。

如果我们再拿鸵鸟来测试这段代码,结果代码发生了系统除零的异常,明显不符合我们的预期。

我们一讲到鸟就认为它能飞,有的鸟确实能飞,但不是所有的鸟都能飞(问题就是出在这里)。

可以看出,Ostrich类和Bird类之间的继承关系违反了里氏代换原则,它们之间的继承关系不成立,鸵鸟不是鸟。

 

里氏替换原则总结

里氏替换原则是实现抽象化的一种规范,只要能做到子类可以完全替代其父类的行为,那么新增加的具体子类在重写父类的行为时,不会对客户代码产生任何不良的影响。

里氏替换原则是使代码符合开闭原则的一个重要保证,子类尽量不要重写父类的方法,这就是里氏替换原则的核心精髓。

 

陈睿mikechen

10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

关注「mikechen」公众号,获取更多技术干货!

后台回复面试即可获取《史上最全阿里Java面试题总结》,后台回复架构,即可获取《阿里架构师进阶专题全部合集

评论交流
    说说你的看法