## 一、继承的问题
>我们知道Java的三大特性:封装,继承,多态。Java 继承有很多优点,是减少重复代码的可靠手段。
但是继承同时存在一些`缺点`:
1.类的耦合性增加了。比如父类更改之后子类也同时需要更改
2.降低代码灵活性。因为继承时,父类会对子类有约束性
我们使用`里氏替换原则`,可以减少继承带来的问题。
## 二、定义
```
里氏替换原则(LSP)指的是所有引用基类的地方都可以透明的使用其子类的对象
可以理解为:只要有父类出现的地方,都可以使用子类来替代。而且不会出现任何错误或者异常。
但是反过来却不行。子类出现的地方,不能使用父类来替代。
如果不符合上述的规定的话,我们可以想象子类的实例化调用方法时候,调用的却是父类的方法。
会出现意想不到的结果
```
## 三、具体约束
1. 子类必须实现父类的抽象方法,但不得重写父类的非抽象(已实现的)方法。
2. 子类中可增加自己特有的方法。(可以随时扩展)
3. 当子类覆盖或者实现父类的方法时,方法的前置条件(方法形参)要比父类输入参数更加宽松。
否则会调用到父类的方法。
4. 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
否则会调用到父类的方法。
>在讲开闭原则的时候埋下了一个伏笔,在获取折扣时重写覆盖了父类的 getPrice() 方法,增加了一个获取原价的方法 getOriginPrice(),显然就违背了里氏替换原则。我们修改一下代码,不应该覆盖 getPrice() 方法,增加 getDiscountPrice() 方法:
~~~
public class JavaDiscountCourse extends JavaCourse {
public JavaDiscountCourse(Integer id, String name, Double price) {
super(id, name, price);
}
public Double getDiscountPrice() {
return super.getPrice() * 0.61;
}
}
~~~
>里氏替换原则只存在于父类与子类之间,约束继承泛滥
## 四、最佳实践
>我们最好将父类定义为抽象类,并定义抽象方法,让子类重新定义这些方法,
当父类是抽象类时候,父类不能实例化
- 前言
- 第一章 设计七大原则
- 第1节 开闭原则
- 第2节 依赖倒置原则
- 第3节 单一职责原则
- 第4节 接口隔离原则
- 第5节 迪米特法则
- 第6节 里氏替换原则
- 第7节 合成复用原则
- 第二章 简单工厂模式
- 第1节 使用场景
- 第2节 示例代码
- 第三章 创建者模式
- 第1节 工厂方法模式
- 第2节 抽象工厂模式
- 第3节 建造者模式
- 第4节 原型模式
- 第5节 单例模式
- 第四章 结构型模式
- 第1节 适配器模式
- 第2节 桥接模式
- 第3节 组合模式
- 第4节 装饰者模式
- 第5节 外观模式
- 第6节 享元模式
- 第7节 代理模式
- 第五章 行为模式
- 第1节 责任链模式
- 第2节 命令模式
- 第3节 迭代器模式
- 第4节 中介者模式
- 第5节 备忘录模式
- 第6节 观察者模式
- 第7节 状态模式
- 第8节 策略模式
- 第9节 模板方法模式
- 第10节 访问者模式
- 第11节 解释器模式