开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
基本介绍
- 里氏替换原则(Liskov Substitution Principle)在,1988 年,由麻省理工学院的一位姓里的女士提出。
- 所有使用父类对象的地方,都应该可以透明的替换为子类的对象。
- 在使用继承时,遵循里氏替换原则,在子类中尽量不要重写父类的方法
- 里氏替换原则告诉我们,继承实际上让两个类耦合性增强了,在适当的情况下,可以通过聚合,组合,依赖 来解决问题。
- 关于重写
-
重写的方法不能比被重写的方法抛出更宽泛的异常
-
重写的方法不能比被重写的方法有更严格的修饰符
-
为什么要有这两个限制:
- 保证子类对象替换父类对象之后,语法不会报错。 符合里氏替换原则。
-
判断两个类是否可以继承
- 是否存在 is a 关系
- 是否可以实现子类透明的替换父类
代码举例
反例
-
代码
//长方形 class Rectangle{ private double length; private double width; public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } @Override public String toString() { return "Rectangle{" + "length=" + length + ", width=" + width + '}'; } } // 正方形 class Square extends Rectangle{ // 边长 private double sidLength; @Override public double getLength() { return sidLength; } @Override public void setLength(double length) { this.sidLength = length; } @Override public double getWidth() { return sidLength; } @Override public void setWidth(double width) { this.sidLength = width; } @Override public String toString() { return "sidLength = " + this.sidLength; } } class Utils{ //变形 让宽等与长 public static void transform(Rectangle rectangle){ while (rectangle.getWidth() < rectangle.getLength()){ rectangle.setWidth(rectangle.getWidth()+1); System.out.println("rectangle.width = " + rectangle.getWidth()); } } } public class negtive.AppTest { public static void main(String[] args) { //创造长方形 Rectangle rectangle = new Rectangle(); rectangle.setWidth(10); rectangle.setLength(20); System.out.println(rectangle); //变形 Utils.transform(rectangle); System.out.println(rectangle); //创造正方形 Square square = new Square(); square.setWidth(10); square.setLength(20); System.out.println(square); //变形 Utils.transform(square); //死循环 System.out.println(square); } } -
分析
- 在用正方形替换长方形父类之后,发现程序的逻辑变为死循环。不符合里氏替换原则。
正例
-
代码
//长方形 class Rectangle{ private double length; private double width; public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } @Override public String toString() { return "Rectangle{" + "length=" + length + ", width=" + width + '}'; } } // 正方形 class Square{ // 边长 private double sidLength; public double getSidLength() { return sidLength; } public void setSidLength(double sidLength) { this.sidLength = sidLength; } } class Utils{ //变形 让宽等与长 public static void transform(Rectangle rectangle){ while (rectangle.getWidth() <= rectangle.getLength()){ rectangle.setWidth(rectangle.getWidth()+1); System.out.println("rectangle.width = " + rectangle.getWidth()); } } } public class negtive.AppTest { public static void main(String[] args) { //创造长方形 Rectangle rectangle = new Rectangle(); rectangle.setWidth(10); rectangle.setLength(20); System.out.println(rectangle); //变形 Utils.transform(rectangle); System.out.println(rectangle); } } -
分析
断绝继承关系