0104_里氏替换原则
定义:子类必须能够替换它们的基类而不影响程序的正确性。这意味着:
- 子类必须保持父类的行为约定
- 子类不能加强前置条件或削弱后置条件
- 子类不能抛出父类未声明的异常
场景
这里还以人类对象为例,人类属性有年龄、名称,动作有吃饭、行走等。

BaseHuman类
- 职责:只处理人类基本属性和基本生存行为
- 稳定性高:这些是所有人共有的基本特征和行为
- 易于扩展:可作为其他人类类型的基类
public class BaseHuman {
// 年龄属性
private int age;
// 姓名属性
private String name;
public BaseHuman(int age, String name) {
this.age = age;
this.name = name;
}
/**
* 获取姓名
* @return 姓名
*/
public String getName() {
return name;
}
/**
* 吃饭方法
*/
public void eat() {
System.out.println(getName() + "在吃饭");
}
/**
* 行走方法
*/
public void walk() {
System.out.println(getName() + "在行走");
}
}
反例
InvalidHuman类
- 职责:违反里氏替换原则的人类实现
public class InvalidHuman extends BaseHuman {
public InvalidHuman(int age, String name) {
super(age, name);
}
/**
* 重写eat方法,使其抛出异常,违反了里氏替换原则
* 父类方法是正常执行,而子类抛出异常,导致替换时行为不一致
*/
@Override
public void eat() {
throw new UnsupportedOperationException("InvalidHuman不能吃饭");
}
/**
* 重写walk方法,使其行为与父类不一致
* 父类是简单输出,而子类添加了额外约束
*/
@Override
public void walk() {
// 假设这类人只能在特定条件下行走
if (Math.random() < 0.9) {
throw new RuntimeException("InvalidHuman行走失败");
}
System.out.println(getName() + "在行走(很困难)");
}
}
在反例中,InvalidHuman类违反里氏替换原则,子类的逻辑与父类的逻辑不一致,如果使用子类替换父类,可能会发生异常。
正例
NormalHuman类
- 职责:处理普通人的行为
public class NormalHuman extends BaseHuman {
/**
* 构造方法
* @param age 年龄
* @param name 姓名
*/
public NormalHuman(int age, String name) {
super(age, name);
}
/**
* 重写吃饭方法
* 普通人特有的吃饭行为
*/
@Override
public void eat() {
System.out.println("我是普通人,正在吃饭");
}
}
总结
里氏替换原则保证了面向对象的多态性能够可靠工作。正例中的NormalHuman可以安全替换BaseHuman,而InvalidHuman的异常行为会导致程序违反使用者对基类的合理预期。遵守LSP能使继承体系更加健壮,减少意外的行为差异。

浙公网安备 33010602011771号