里氏替换原则表示如果对每一个类型为 S 的对象 o1 都有类型为 T 的对象 o2 ,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时 ,程序 P 的行为没有发生变化 ,那么类型 S 是类型 T 的子类型。也就是说,在程序中可以将子类对象替换父类对象,而程序逻辑不变。
里氏替换原则是继承复用的基础,它体现了子类和父类之间的关系。
如果一个软件能够遵循里氏替换原则,那么它就具有以下两个优点:
举个例子,假设我们有一个动物类 Animal,它有一个方法 run(),表示动物可以奔跑。然后我们定义了一个鸟类 Bird 来继承 Animal 类,并重写了 run() 方法,表示鸟可以飞行。这个类就违反了里氏替换原则,因为它改变了父类的行为含义,使得在程序中无法将 Bird 对象替换 Animal 对象,而不改变程序的逻辑。代码如下:
class Animal {
public void run() {
System.out.println("动物可以奔跑");
}
}
class Bird extends Animal {
@Override
public void run() {
System.out.println("鸟可以飞行");
}
}
为了遵循里氏替换原则,我们应该将 Animal 类设计成一个抽象类,并定义一个抽象方法 move()。然后,针对不同的动物类型,定义不同的子类来继承 Animal 类,并实现 move() 方法。这样,在程序中可以将任何一个子类对象替换父类对象,而不改变程序的逻辑。代码如下:
abstract class Animal {
public abstract void move();
}
class Dog extends Animal {
@Override
public void move() {
System.out.println("狗可以奔跑");
}
}
class Bird extends Animal {
@Override
public void move() {
System.out.println("鸟可以飞行");
}
}
// 其他动物类型的子类省略