一 里氏替换原则(Liskov Substitution Principle, LSP)
要么别继承,如果继承,就要支持父类所有方法
一句话核心思想
“子类可以替换父类,并且程序不会出错。”
(就像你爸的手机你能用,你的手机你爸也能用,谁用都不会出问题!)
通俗解释(现实例子)
假设你有一个 “鸟” 类,它有个方法 “飞”:
class Bird {void fly() {System.out.println("鸟儿飞翔~");}
}
然后你写了个 “企鹅” 类继承 “鸟”:
class Penguin extends Bird {@Overridevoid fly() {throw new RuntimeException("企鹅不会飞!"); // 违背LSP!}
}
问题来了:
- 如果别人调用
Bird bird = new Penguin(); bird.fly();
→ 程序崩溃! - 这就是违反LSP,因为 企鹅(子类)不能安全替换鸟(父类)。
正确做法(遵守LSP)
- 要么别继承(企鹅本就不该继承“会飞的鸟”):
class Bird { } // 普通鸟 class FlyingBird extends Bird { void fly() { ... } } // 会飞的鸟 class Penguin extends Bird { } // 企鹅不会飞,但不继承FlyingBird
- 要么子类别破坏父类行为(如果继承,就要支持父类所有方法):
class Penguin extends Bird {@Overridevoid fly() {System.out.println("企鹅不会飞,但可以游泳!"); // 不报错,而是优雅处理} }
关键记忆点(LSP核心规则)
- 子类必须完全支持父类的功能(不能“阉割”父类方法)。
- 子类可以扩展功能,但不能改变父类的初衷(比如父类是“飞”,子类不能改成“跑”)。
- 调用父类的地方,换成子类也不会报错(这是黄金检验标准!)。
实际代码中如何遵守?
✅ 正确示范:
- 父类
File
有read()
方法,子类PDFFile
和TXTFile
都实现read()
,但内部逻辑不同。 - 父类
List
有add()
方法,子类UnmodifiableList
直接禁止修改(抛出明确异常,而非隐藏错误)。
❌ 错误示范:
- 父类
Rectangle
有setWidth()
和setHeight()
,子类Square
改成只用一个边长(违反数学逻辑)。 - 父类
Database
有connect()
,子类MockDatabase
的connect()
直接返回null
(应返回模拟连接)。
一句话总结
“子类要像充话费送的亲儿子,不能像捡来的干儿子——该有的功能一个不能少,但可以更牛逼!”
二 为什么继承xxxFragment
违反里氏替换原则(LSP):
- LSP核心原则:
- 子类应该能够替换父类,而不改变程序的正确性
- 子类可以扩展父类的功能,但不应该改变父类的功能
xxxFragment
包含特定的空调业务逻辑:
class xxxFragment : BasexxxFragment() {private val frontFragment by lazy { FxxFragment() }private val rearFragment by lazy { RxxFragment() }private fun setupFragments() {// 空调特有的前后排切换逻辑childFragmentManager.beginTransaction().add(R.id.fragmentContainer, rearFragment).hide(rearFragment).add(R.id.fragmentContainer, frontFragment).commit()}
}
- 违反LSP的情况:
- 如果其他Fragment(如
MassageFragment
)继承AirConditionFragment
- 它会继承到不需要的空调UI逻辑
- 必须重写或忽略父类的空调相关方法
- 这破坏了父类的行为预期
正确的做法是创建SharedViewModelFragment
作为基类,因为:
4. 只包含共享的ViewModel逻辑
5. 不包含具体业务实现
6. 子类可以安全扩展而不违反LSP
三 里氏替换原则的具体含义可以概括为以下几点
1.子类必须能够替换其基类:在任何基类可以出现的地方,子类都可以出现,并且不会改变程序的行为。
2.子类扩展而非修改:子类可以增加新的行为,但不能改变或删除父类已有的功能。这意味着子类可以添加新的方法或重载父类的方法,但不能重写父类的非抽象方法。
3. 对开闭原则的补充:里氏替换原则是对开闭原则(Open-Closed Principle)的补充,强调通过继承和抽象化来实现软件的可扩展性和可维护性。
参考:
https://blog.csdn.net/lilinhai548/article/details/141287849