里氏替换原则(LSP)

太好了,现在我们来讲解 SOLID 中非常核心的 LSP:里氏替换原则(Liskov Substitution Principle)

我会一步步讲清楚:

  • 什么是 LSP?
  • 为什么重要?
  • 优劣分析
  • Python 正反例子
  • 清晰的结构图(Mermaid)

🧠 一句话定义(LSP)

任何父类出现的地方,都应该可以用它的子类替代,并且不会导致程序逻辑出错。

简化记忆:

子类能替换父类,并保持行为正确。


🎯 为什么需要?

当你用多态写程序(比如用父类来调用子类对象)时:

如果子类违背了父类的行为约定 ,会导致系统运行时出现不符合预期的错误 ,就违反了 LSP


✅ 优点 vs ❌ 缺点

优点 缺点
子类更符合父类语义 设计成本提升
多态行为更安全 有时限制了子类个性
程序行为更稳定 实现复杂逻辑更麻烦

🔥 常见违反 LSP 的坑

子类复写方法后,行为和父类完全不同、甚至反逻辑。


❌ 违反 LSP 的反面例子

python 复制代码
class Bird:
    def fly(self):
        print("I can fly")

class Ostrich(Bird):
    def fly(self):
        raise Exception("I can't fly")  # ❌ 鸵鸟不能飞

def let_it_fly(bird: Bird):
    bird.fly()

let_it_fly(Ostrich())  # ❌ 虽然语法对,但运行崩了

问题:

  • OstrichBird,但替换后程序出错 → 违反 LSP

✅ 遵守 LSP 的正确做法(更合理抽象)

python 复制代码
from abc import ABC, abstractmethod

# 抽象出"会飞的鸟"和"不飞的鸟"
class Bird(ABC):
    @abstractmethod
    def eat(self):
        pass

class Flyable(ABC):
    @abstractmethod
    def fly(self):
        pass

class Sparrow(Bird, Flyable):
    def eat(self): print("Sparrow eats")
    def fly(self): print("Sparrow flies")

class Ostrich(Bird):
    def eat(self): print("Ostrich eats")
    # 没有 fly 方法

# ✅ 函数只接受会飞的鸟
def let_it_fly(bird: Flyable):
    bird.fly()

let_it_fly(Sparrow())  # ✅ OK
# let_it_fly(Ostrich())  # ❌ 语法报错,避免运行期出错

通过接口分离 + 更精确抽象,让程序在编译期就避免 LSP 问题。


🧭 结构图(Mermaid)

Bird +eat() Flyable +fly() Sparrow +eat() +fly() Ostrich +eat()


🏁 总结口诀

原则 理解方式 记忆口诀
✅ 里氏替换原则 子类能替换父类,行为不崩溃 "不是你的儿子,不要继承你"
🚨 如何避免 抽象设计精准、使用接口拆分 "不要滥用继承,改用组合或接口"

📌 实际应用场景

  • 游戏角色:近战 vs 远程,应分成独立能力而不是强行继承
  • 网络传输协议:TCP vs UDP,公共方法和行为应明确分离
  • 交通工具:汽车 vs 船,不要硬继承"能跑的交通工具"

需要我帮你写一个 支付系统用户系统中角色模型 来体现 LSP 吗?实战会更直观哦。你想继续扩展哪部分?🔍

相关推荐
怪力左手7 天前
LSP、DAP语言服务器
运维·服务器·里氏替换原则
MediaTea1 个月前
Python:里氏替换原则(LSP)
里氏替换原则
聊天QQ:276998851 个月前
车桥耦合matlab程序。 使用newmark法进行数值积分,考虑不平顺车辆-无砟轨道-桥梁耦...
里氏替换原则
沟通QQ:276998851 个月前
基于多能互补的热电联供型微网优化运行探索
里氏替换原则
烤麻辣烫2 个月前
23种设计模式(新手)-5里氏替换原则
java·学习·设计模式·intellij-idea·里氏替换原则
口袋物联2 个月前
图解码说-六大设计原则(开闭原则、单一职责原则、里氏替换原则、接口隔离原则、依赖倒置原则、迪米特法则)
接口隔离原则·依赖倒置原则·里氏替换原则·开闭原则·单一职责原则·设计模式原则·迪米特法原则
玩机达人883 个月前
三星S25Ultra/S24安卓16系统Oneui8成功获取完美root权限+LSP框架
android·linux·里氏替换原则
云点一点点3 个月前
完全理解您的要求。我将输出一个关于MySQL的原创文章标题。MySQL并发控制的幕后锁、事务隔离级别与性能优化实战
里氏替换原则
土了个豆子的4 个月前
02.继承MonoBehaviour的单例模式基类
开发语言·visualstudio·单例模式·c#·里氏替换原则
小蜗牛在漫步4 个月前
设计模式六大原则2-里氏替换原则
设计模式·里氏替换原则