里氏替换原则的定义:
继承必须确保超类所拥有的性质在子类中仍然成立。它反映了积累与子类之间的关系,是对开闭原则的补充,是对实现抽象化的具体步骤的规范。
里氏替换原则的作用:
(1)里氏替换原则是实现开闭原则的重要方式之一。
(2)它克服了继承中重写父类造成的可复用性变差的缺点。
(3)他是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
里氏替换原则的实现方法:
里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新
增功能外,尽量不要重写父类的方法。如果通过重写父类的方法来完成新的功能,这样写起来虽然简单,但是整个继承体系的可复用性会
比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。如果程序违背了里氏替换原则,则继承类的对象在基类出现的地方
会出现运行错误。这时其修正方法是:取消原来的继承关系,重新设计它们之间的关系。
下面以“几维鸟不是鸟”为例说明里氏替换原则:
UML类图:
package lsp;
//动物
public class Animal {
protected double runSpeed;
// 奔跑速度
public void setRunSpeed(double runSpeed) {
this.runSpeed = runSpeed;
}
// 奔跑时间
public double getRunTime(double distance){
return (distance / runSpeed);
}
}
package lsp;
//鸟
public class Bird extends Animal{
protected double flySpeed;
// 飞行速度
public void setSpeed(double speed) {
flySpeed = speed;
}
// 飞行时间
public double getFlyTime(double distance){
return (distance / flySpeed);
}
}
package lsp;
//燕子
public class Swallow extends Bird {
protected double flySpeed;
// 飞行速度
@Override
public void setSpeed(double flySpeed) {
this.flySpeed = flySpeed;
}
// 飞行时间
@Override
public double getFlyTime(double distance) {
return (distance / flySpeed);
}
public Swallow() {
}
}
package lsp;
//几维鸟
public class BrownKiwi extends Animal{
protected double runSpeed;
// 奔跑速度
@Override
public void setRunSpeed(double runSpeed) {
this.runSpeed = runSpeed;
}
// 奔跑时间
@Override
public double getRunTime(double distance) {
return (distance / runSpeed);
}
}
package lsp;
//访问类
public class LSPTest {
public static void main(String[] args) {
Bird bird = new Swallow();
Animal animal = new BrownKiwi();
System.out.println("如果速度为120");
bird.setSpeed(120);
animal.setRunSpeed(120);
System.out.println("飞行或奔跑300千米");
double flyTime = bird.getFlyTime(300);
double runTime = animal.getRunTime(300);
System.out.println("燕子将飞行" + flyTime + "小时");
System.out.println("几维鸟将奔跑" + runTime + "小时");
}
}