里氏替换原则LSP(Liskov Substitution Principle)主要阐述了有关继承的一些原则。子类可以扩展父类的功能,但不能改变父类原有的功能,如果重写了父类的方法,就会降低整个继承体系的复用性,如果违背了里氏替换原则,就很有可能出现运行错误
这里以一个鸟的例子来阐述:
首先定义一个超类鸟,它具有飞行速度的属性和飞的功能,然后设计两个子类,一个是燕子,一个是企鹅,这两个动物都是鸟类,但是企鹅不会飞,首先我们以普通的方式来演示继承关系,并实现飞行测试
public class Bird {
double speed;
//d的距离需要飞行的时间
public double getSpeedTime(double d) {
return d / speed;
}
//设置鸟的飞行速度
public void setSpeed(double speed) {
this.speed = speed;
}
}
public class Swallow extends Bird {
}
public class Penguin extends Bird {
@Override
public void setSpeed(double speed) {
super.speed = 0;
}
}
public class Main {
public static void main(String[] args) {
double d = 100;
Bird bird = new Swallow();
Bird bird1 = new Penguin();
bird.setSpeed(100);
System.out.println(bird.getSpeedTime(d));
System.out.println(bird1.getSpeedTime(d));
}
}
这样运行的结果如下图,企鹅需要的时间是Infinity,这是不符合逻辑的
下面来解决此问题,也就是李氏替换原则,不要重写,给企鹅定义自己的方法,也就是走
public class Animal {
//这里有一些动物的属性和方法就不一一列出了
}
public class Bird extends Animal{
double speed;
//d的距离需要飞行的时间
public double getSpeedTime(double d) {
return d / speed;
}
//设置鸟的飞行速度
public void setSpeed(double speed) {
this.speed = speed;
}
}
public class Swallow extends Bird {
}
/**
* 这里直接继承Animal,因为它不具有飞的功能
*/
public class Penguin extends Animal{
double walk;
public void setSpeed(double walk) {
this.walk = walk;
}
public double getSpeedTime(double d) {
return d / walk;
}
}
public class Main {
public static void main(String[] args) {
double d = 100;
Swallow swallow = new Swallow();
Penguin penguin = new Penguin();
swallow.setSpeed(100);
penguin.setSpeed(20);
System.out.println(swallow.getSpeedTime(d));
System.out.println(penguin.getSpeedTime(d));
}
}
运行结果:
总结一句话,里氏替换主要解决,什么时候应该使用继承,什么时候不应该使用继承的问题!