当前位置: 首页 > news >正文

Liskov Substitution Principle(LSP 里氏替换原则)

一.what is Liskov Substitution Principle

里氏替换原则是面向对象设计中的五大SOLID原则之一,是开闭原则的重要补充。它规定了子类可以扩展基类的功能,但不能改变基类原有的行为。


二.LSP的设计准则

LSP强调了继承不仅是“is a”的关系,并且行为上必须是“is-substitutable-for”(可以完全替换)的关系。

  • 前置条件(Preconditions):子类方法的前置条件不能比基类更严格(参数范围要更宽松或相等)。
  • 后置条件(Postconditions):子类方法的后置条件不能比基类更宽松(返回值范围要更严格或相等)。
  • 不变式(Invariants):子类必须维护基类定义的不变式。
  • 异常(Exceptions):子类方法不能抛出比基类更多的异常类型。

三.举例

3.1 基类鸟和和子类鸵鸟

语义上:鸵鸟是一种鸟,正确。
行为上:如果基类Bird有fly()方法,正常鸟可以飞,但鸵鸟不能飞,或者执行飞了会抛异常(子类方法变得更严格)。这时用鸵鸟替换Bird,就会破坏程序原有行为, 违反LSP。


3.2 linux虚拟文件系统

vfs.h

点击查看代码
#ifndef VFS_H
#define VFS_H#include <stdio.h>
#include <stddef.h>// 1. 定义操作契约 (类似 C++ 的纯虚类)
struct file_operations {int (*open)(struct my_file *file);ssize_t (*read)(struct my_file *file, char *buf, size_t count);
};// 2. 定义通用对象
struct my_file {const struct file_operations *f_ops; // 父类接口指针void *private_data;                  // 指向具体的“子类”数据
};// 3. 通用高层接口:无论什么文件,调用者只用这两个函数
void vfs_open(struct my_file *file);
void vfs_read(struct my_file *file, char *buf, size_t count);#endif

vfs.c
点击查看代码
#include "vfs.h"void vfs_open(struct my_file *file) {if (file->f_ops->open) {file->f_ops->open(file);}
}void vfs_read(struct my_file *file, char *buf, size_t count) {if (file->f_ops->read) {file->f_ops->read(file, buf, count);}
}

实现磁盘设备和键盘设备驱动

driver.c

点击查看代码
#include "vfs.h"
#include <stdlib.h>// --- 子类 A: 磁盘文件 ---
struct disk_file {const char *disk_path;int sector_id;struct my_file vfs_node; // 嵌入父类对象
};static int disk_open(struct my_file *f) {printf("[Disk] 寻道到起始扇区...\n");return 0;
}static ssize_t disk_read(struct my_file *f, char *b, size_t c) {printf("[Disk] 从物理磁盘读取 %zu 字节数据\n", c);return c;
}const struct file_operations disk_fops = { .open = disk_open, .read = disk_read };// --- 子类 B: 键盘设备 ---
struct keyboard_dev {int irq_line;struct my_file vfs_node;
};static int kbd_open(struct my_file *f) {printf("[KBD] 激活中断线,准备监听按键...\n");return 0;
}static ssize_t kbd_read(struct my_file *f, char *b, size_t c) {printf("[KBD] 从缓冲区获取击键数据...\n");return c;
}const struct file_operations kbd_fops = { .open = kbd_open, .read = kbd_read };

main.c
点击查看代码
#include "vfs.h"// 外部驱动定义的 ops
extern const struct file_operations disk_fops;
extern const struct file_operations kbd_fops;int main() {char buffer[128];// 1. 创建磁盘文件对象struct my_file file_a = { .f_ops = &disk_fops };// 2. 创建键盘设备对象struct my_file file_b = { .f_ops = &kbd_fops };// 3. 里氏替换原则的体现:// vfs_read 接受的是 struct my_file*。// 无论底层是磁盘还是键盘,对于 vfs_read 来说都是一样的。printf("--- 操作文件 A ---\n");vfs_open(&file_a);vfs_read(&file_a, buffer, 100);printf("\n--- 操作文件 B ---\n");vfs_open(&file_b);vfs_read(&file_b, buffer, 100);return 0;
}


这个例子满足里氏替换原则:

  • 行为一致性:vfs_read 预期调用 read 后会得到数据。disk_read 和 kbd_read 虽然获取数据的手段不同(一个读磁道,一个等中断),但结果都符合“填充缓冲区并返回”的契约。

  • 完全替换:在 main.c 中,我们可以把 file_a 换成 file_b 而不需要修改 vfs_read 的任何一行代码。

http://www.jsqmd.com/news/405768/

相关文章:

  • python: Visitor Pattern
  • python+uniapp微信小程序的毕业论文选题系统设计与实现
  • python+uniapp微信小程序的校园外卖点餐点单系统 商家协同过滤
  • 闲置不用的沃尔玛购物卡可以回收变现吗 - 抖抖收
  • 你说 还未解锁,那么“/data/log/“; 为什么这个路径可以?不是还未解锁吗?
  • 白嫖永久免费域名,托管到 CloudFlare
  • 2026年目前比较好的金属探测门品牌找哪家,金属探测门/安检仪/安检设备/智能安检/安检机,金属探测门源头厂家排行榜单 - 品牌推荐师
  • 兑换的京东e卡套装在哪里回收划算? - 抖抖收
  • 超级人工智能(AGI)是否是大模型的必然发展方向?
  • 破解合规与迭代双重难题:研发项目管理系统的全行业适配方案——全星研发管理APQP软件系统
  • 高端制造企业QMS选型指南:QMS系统全方位解读——全星质量管理QMS软件系统推荐
  • 基于单片机的防火防盗报警系统设计方案
  • 用SHAP进行多模型解释性分析:类别与数值预测案例
  • CT断层成像系列09——三维锥束Shepp-Logan头模型设计实现与正向投影实现(附Matlab代码)
  • 2026曝气池清理厂家推荐,专业实力看得见,专业的曝气池清理公司推荐榜深度剖析助力明智之选 - 品牌推荐师
  • Czkawka下载安装完整教程:免费重复文件清理工具(附安装包,2026最新) - xiema
  • 笛卡尔树
  • 外包项目压力山大,XinServer 是我的救命稻草
  • 2026年欧曼增压器市场:直销厂家口碑现状解析,欧宝A14net增压器/福康增压器,增压器厂商排行 - 品牌推荐师
  • [AI提效-30]- 2026年国内OPC社区全景地图
  • 2026污水处理设备指南:口碑佳的品牌推荐,智能一体化污水处理设备/帘式MBR膜,污水处理设备厂家哪家靠谱 - 品牌推荐师
  • P7708 题解
  • 大模型时代交互革命:小白也能秒懂,收藏必备,开启认知新纪元!
  • 保姆级实测!小白5行代码接入谷歌Gemini 3.1 Pro,复杂推理能力翻倍,速收藏!
  • JVM--16-面试题2:请详细描述 JVM 的运行时数据区
  • CF1304C
  • 技术演进中的开发沉思-371:final 关键字(中)
  • 常规正则表达式手册
  • 一款纯VF控制的变频器方案方案说明:可做0.2KW7.5KW/220V,0.2KW75KW/380V
  • python+uniapp微信小程序的连锁奶茶店甜品点单系统