竞价网站建设,制作网站公司哪个好,深圳建站公司企业,淄博网站制作公司服务目录1 里氏替换原则2 里氏替换原则应用1 里氏替换原则
里氏替换原则#xff08;Liskov Substitution Principle,LSP#xff09;是指如果对每一个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都替换成 o2 时#xff0c;程序 P…
目录1 里氏替换原则2 里氏替换原则应用1 里氏替换原则
里氏替换原则Liskov Substitution Principle,LSP是指如果对每一个类型为 T1 的对象 o1,都有类型为 T2 的对象 o2,使得以 T1 定义的所有程序 P 在所有的对象 o1 都替换成 o2 时程序 P 的行为没有发生变化那么类型 T2 是类型 T1 的子类型。
定义看上去还是比较抽象我们重新理解一下可以理解为一个软件实体如果适用一个父类的话那一定是适用于其子类所有引用父类的地方必须能透明地使用其子类的对象子类对象能够替换父类对象而程序逻辑不变。根据这个理解我们总结一下
引申含义子类可以扩展父类的功能但不能改变父类原有的功能。 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 getOriginPrice(){return super.getPrice();}public Double getPrice(){return super.getPrice() * 0.61;}}
更正
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;}
}2 里氏替换原则应用
使用里氏替换原则有以下优点
1、约束继承泛滥开闭原则的一种体现。 2、加强程序的健壮性同时变更时也可以做到非常好的兼容性提高程序的维护性、扩展性。降低需求变更时引入的风险。现在来描述一个经典的业务场景用正方形、矩形和四边形的关系说明里氏替换原则我们都知道正方形是一个特殊的长方形那么就可以创建一个长方形父类 Rectangle 类
public class Rectangle {private long height;private long width;public long getHeight() {return height;}public void setHeight(long height) {this.height height;}public long getWidth() {return width;}public void setWidth(long width) {this.width width;}
}创建正方形 Square 类继承长方形
public class Square extends Rectangle {private long length;public long getLength() {return length;}public void setLength(long length) {this.length length;}Overridepublic long getHeight() {return getLength();}Overridepublic void setHeight(long height) {setLength(height);}Overridepublic long getWidth() {return getLength();}Overridepublic void setWidth(long width) {setLength(width);}
}在测试类中创建 resize()方法根据逻辑长方形的宽应该大于等于高我们让高一直自增知道高等于宽变成正方形
public static void resize(Rectangle rectangle){while (rectangle.getWidth() rectangle.getHeight()){rectangle.setHeight(rectangle.getHeight() 1);System.out.println(Width: rectangle.getWidth() ,Height: rectangle.getHeight());}System.out.println(Resize End,Width: rectangle.getWidth() ,Height: rectangle.getHeight());
}测试代码
public static void main(String[] args) {
Rectangle rectangle new Rectangle();
rectangle.setWidth(20);
rectangle.setHeight(10);
resize(rectangle);
}运行结果
发现高比宽还大了在长方形中是一种非常正常的情况。现在我们再来看下面的代码把长方形Rectangle 替换成它的子类正方形 Square修改测试代码
public static void main(String[] args) {Square square new Square();square.setLength(10);resize(square);
}这时候我们运行的时候就出现了死循环违背了里氏替换原则将父类替换为子类后程序运行结果没有达到预期。因此我们的代码设计是存在一定风险的。里氏替换原则只存在父类与子类之间约束继承泛滥。我们再来创建一个基于长方形与正方形共同的抽象四边形 Quadrangle 接口
public interface QuadRangle {long getWidth();long getHeight();
}修改长方形 Rectangle 类
public class Rectangle implements QuadRangle {
private long height;
private long width;public long getHeight() {return height;}public void setHeight(long height) {this.height height;}public long getWidth() {return width;}public void setWidth(long width) {this.width width;}
}修改正方形类 Square 类
public class Square implements QuadRangle {private long length;public long getLength() {return length;}public void setLength(long length) {this.length length;}public long getWidth() {return length;}public long getHeight() {return length;}
}此时如果我们把 resize()方法的参数换成四边形 Quadrangle 类方法内部就会报错。因为正方形 Square 已经没有了 setWidth()和 setHeight()方法了。因此为了约束继承泛滥resize()的方法参数只能用 Rectangle 长方形。当然我们在后面的设计模式中还会继续深入讲解。