2026-10-21 22:57:01
里氏替换原则(LSP)的核心思想是:子类对象能够无缝替换父类对象出现在程序中的任何位置,且不破坏程序的正确性和行为一致性。 这一原则强调继承关系中子类必须严格遵循父类的契约,确保多态调用的安全性。
在Java继承中的具体体现子类不改变父类的契约
参数约束:子类重写方法时,参数类型不能比父类更严格(即不能缩小输入范围)。例如,父类方法接受Object类型参数,子类不能改为仅接受String类型。
返回值协变:子类方法的返回值类型可以比父类更具体(协变返回类型)。例如,父类返回Number,子类可返回Integer。
异常限制:子类方法不能抛出父类未声明的新受检异常(如IOException),但可以抛出更具体的异常或运行时异常。
行为一致性
子类必须保持与父类相同的行为逻辑。例如:
若父类的calculateArea()方法用于计算面积,子类重写时也应返回面积值,而非周长或其他无关结果。
若父类方法约定不返回null,子类也需遵守此约定。
反例:若父类Bird的fly()方法默认支持飞行,子类Penguin重写时抛出UnsupportedOperationException,则违反LSP。
避免削弱父类能力
子类不应通过重写方法破坏父类的预期行为。典型反例是“正方形继承长方形”:
长方形类提供setWidth(int w)和setHeight(int h)方法,允许独立修改宽高。
正方形类强制宽高相等,重写这两个方法时联动修改,导致调用方预期的独立修改行为失效,违反LSP。
正确做法:若子类无法满足父类的所有行为,应通过组合而非继承实现关系。
多态调用的安全性
当父类引用指向子类对象时(如List<String> list = new ArrayList<>()),调用方法应符合预期。例如:
父类List的add()方法允许插入元素,子类ArrayList必须支持此操作。
若子类重写方法后导致程序崩溃或结果异常(如父类sort()默认升序,子类改为降序但未文档说明),则违反LSP。
遵循LSP可提高代码的可扩展性和可维护性,避免因继承导致的设计问题。例如,在集合框架中,ArrayList对List接口的完整实现确保了多态调用的安全性;而若自定义集合类破坏了add()或remove()的契约,则会引发不可预测的错误。