03 里氏替换原则
官方定义:
里氏替换原则(Liskov Substitution Principle,LSP)是由麻省理工学院计算机科学系教授芭芭拉·利斯科夫于 1987 年在“面向对象技术的高峰会议”(OOPSLA)上发表的一篇论文《数据抽象和层次》(Data Abstractionand Hierarchy)里提出的.
她在论文中提到:如果S是T的子类型,对于S类型的任意对象,如果将他们看作是T类型的对象,则对象的行为也理应与期望的行为一致。
子类对象能够替换程序中父类对象出现的任何地方,并且保证原来程序的逻辑行为不变及正确性不被破坏。
如何理解里氏替换原则?
要理解里氏替换原则,其实就是要理解两个问题:
什么是替换?
什么是与期望行为一致的替换(Robert Martin所说的“必须能够替换”)?
1 ) 什么是替换 ?
替换的前提是面向对象语言所支持的多态特性,同一个行为具有多个不同表现形式或形态的能力。

2 ) 什么是与期望行为一致的替换?
在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类的实现,都与接口或基类方法的期望行为一致。
不需要关心是哪个类对接口进行了实现,因为不管底层如何实现,最终的结果都会符合接口中关于方法的描述(也就是与接口中方法的期望行为一致).
或者说接口或基类的方法是一种契约,使用方按照这个契约来使用,派生类也按照这个契约来实现。这就是与期望行为一致的替换。
场景案例
比如在一个商城项目中,有3种促销活动:
1)PromotionalStrategy (满减活动,两百以上百八折)
2)RebateStrategy(打折活动)
3)ReduceStrategy(返现活动)

public interface Istrategy {public double realPrice(double consumePrice);
}
public class PromotionalStrategy implements Istrategy {public double realPrice(double consumePrice) {
if (consumePrice > 200) {
return 200 + (consumePrice - 200) * 0.8;
} else {
return consumePrice;
}
}
}
public class RebateStrategy implements Istrategy {
private final double rate;
public RebateStrategy() {
this.rate = 0.8;
}
public double realPrice(double consumePrice) {
return consumePrice * this.rate;
}
}
public class ReduceStrategy implements Istrategy {
public double realPrice(double consumePrice) {
if (consumePrice >= 1000) {
return consumePrice - 200;
} else {
return consumePrice;
}
}
}
调用方为Context,在此类中使用接口定义了一个对象
public class Context {
//使用基类定义对象变量
private Istrategy strategy;
// 注入当前活动使用的具体对象
public void setStrategy(Istrategy strategy) {
this.strategy = strategy;
}
// 计算并返回费用
public double cul(double consumePrice) {
// 使用具体商品促销策略获得实际消费金额
double realPrice =
this.strategy.realPrice(consumePrice);
// 格式化保留小数点后1位,即:精确到角
BigDecimal bd = new BigDecimal(realPrice);
bd = bd.setScale(1, BigDecimal.ROUND_DOWN);
return bd.doubleValue();
}
}
Context 中代码使用接口定义对象变量,这个对象变量可以是实现了lStrategy
接口的PromotionalStrategy、RebateStrategy 、 ReduceStrategy任意一个。
里氏代换原则与多态的区别 ?
虽然从定义描述和代码实现上 来看,多态和里式替换有点类似,但它们关
注的角度是不一样的。多态是面向对象编程的一 大特性,也是面向对象编
程语言的一种语法。它是一种代码实现的思路。而里式替换是一种 设计原
则,用来指导继承关系中子类该如何设计,子类的设计要保证在替换父类
的时候,不 改变原有程序的逻辑及不破坏原有程序的正确性。
里氏替换原则和依赖倒置原则,构成了面向接口编程的基础,正因为里氏替换
原则,才使得程序呈现多样性。
相关文章:
03 里氏替换原则
官方定义: 里氏替换原则(Liskov Substitution Principle,LSP)是由麻省理工学院计算机科学系教授芭芭拉利斯科夫于 1987 年在“面向对象技术的高峰会议”(OOPSLA)上发表的一篇论文《数据抽象和层次》&#…...
【微信小程序】无纸化会议OA系统之首页搭建
前言 中国政府意识到信息技术的重要性,并开始积极推动信息产业的发展。一系列政策和措施被制定和执行,以促进信息技术的采用和普及,从而推动数字化时代的到来。为了响应国家推行的数字化时代,本篇文章以会议OA系统为背景进行编写…...
小程序:uniapp解决主包体积过大的问题
已经分包但还是体积过大 运行时勾选“运行时是否压缩代码”进行压缩 在manifest.json配置(开启分包优化) "mp-weixin" : {"optimization" : {"subPackages" : true}//.... },在app.json配置(设置组件按需注入…...
[opencv]图像和特征点旋转
本来说这是很简单的一个内容,图像旋转只需要使用opencv中自带的旋转函数即可完成,但是最近在做特征点旋转的时候发现使用内置rotate函数给图像旋转90度,再用getRotationMatrix2D得出的旋转矩阵对特征点旋转,画出来的特征点位置全部…...
世界粮食日:宏工科技有对策,赋能食品生产高效可持续发展
10月16日是世界粮食日。随着全球人口的增长,人们对高品质食品的需求也越来越大,如何实现“更好生产、更好营养”成为了食品生产与供应的重要话题。15年来,宏工科技专注物料处理自动化领域,提供食品物料处理一站式解决方案以提高生…...
FutureTask配合Thread实现处理有返回结果的源码、逻辑与架构分析
文章目录 1.介绍2.使用示例3.执行过程描述4.整体的关系5.涉及到的核心源码(只提取了关键代码)5.1 Callable5.2 RunnableFuture5.3 FutureTask5.4 Thread 1.介绍 FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况。 2.使用…...
Queue Deque 介绍
目录 一. 前言 二. Queue 接口 三. Deque 接口 一. 前言 Java里有一个叫做Stack的类,却没有叫做Queue的类(它是个接口名字)。当需要使用栈时,Java已不推荐使用Stack,而是推荐使用更高效的ArrayDeque;既然…...
机器学习(23)---Boosting tree(课堂笔记)
文章目录 一、知识记录二、题目2.1 题目12.2 题目22.3 答案书写 一、知识记录 二、题目 2.1 题目1 2.2 题目2 2.3 答案书写...
Excel 导出打不开
$filename iconv("UTF-8", "GB2312//IGNORE", 志愿者列表) . - . date(YmdHis) . .xlsx; header(Content-Type: application/vnd.ms-excel); header(Content-Disposition: attachment;filename".$filename."); header(Cache-Control: max-age0)…...
css钟表数字样式
如图: 代码 font-size: 28px;font-family: Yourname;font-weight: 500;color: #00e8ff;...
一步一步分析ChatGPT,1 粘性,2 传染性, 3 双边网络效应
请按照以下三个维度一步一步分析ChatGPT,1 粘性,2 传染性, 3 双边网络效应,比如亚马逊的买家和商家的关系 ChatGPT的分析 1.1. 粘性 (Stickiness) 定义: 粘性是指产品或服务对用户的吸引力,即用户在使用…...
Arthas(阿尔萨斯):阿里巴巴开源的线上问题诊断工具
背景 通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用 IDE 远程调试。更糟糕的是,在生产环境中调试是不可接受的,因为它会暂停所有线程,导致服务暂停。 开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是,某些问题无法在不同…...
由Django-Session配置引发的反序列化安全问题
漏洞成因 漏洞成因位于目标配置文件settings.py下 关于这两个配置项 SESSION_ENGINE: 在Django中,SESSION_ENGINE 是一个设置项,用于指定用于存储和处理会话(session)数据的引擎。 SESSION_ENGINE 设置项允许您选择不…...
16-spring AOP核心对象的创建
文章目录 1. aop的几个重要概念2. aop bean definition3. AspectJPointcutAdvisor4.AopConfigUtils5.AnnotationAwareAspectJAutoProxyCreator6. 循环依赖1. aop的几个重要概念 参考官方解释:https://docs.spring.io/spring-framework/docs/5.2.9.RELEASE/spring-framework-r…...
Golang 泛型的介绍
引言 Golang是一种现代的编程语言,以其简洁的语法和高效的性能而闻名。然而,与其他一些编程语言相比,Golang在语言层面上缺乏泛型的支持,这使得在处理不同类型的数据时变得有些困难。在本文中,我们将介绍Golang泛型的…...
RK3568笔记四:基于TensorFlow花卉图像分类部署
若该文为原创文章,转载请注明原文出处。 基于正点原子的ATK-DLRK3568部署测试。 花卉图像分类任务,使用使用 tf.keras.Sequential 模型,简单构建模型,然后转换成 RKNN 模型部署到ATK-DLRK3568板子上。 在 PC 使用 Windows 系统…...
甄知科技张礼军:数智化转型助企业破茧成蝶!
数智化浪潮滚滚向前,正席卷各行各业,带领企业从数字化时代跨入数智化时代。可什么是数智化?如何实现数智化转型?已经成为横亘在无数企业面前的大难题! 事实上,数智化是数字化、AI和业务三个要素的交集&…...
Golang Map:高效的键值对容器
1. 引言 在编程中,我们经常需要使用键-值对来存储和操作数据。Golang中提供了一种高效的键值对容器——Map(映射),它提供了快速的查找和插入操作,是处理大量关联数据的理想选择。本文将介绍Golang中的Map,…...
2023年【电工(高级)】报名考试及电工(高级)模拟考试题
题库来源:安全生产模拟考试一点通公众号小程序 2023年【电工(高级)】报名考试及电工(高级)模拟考试题,包含电工(高级)报名考试答案和解析及电工(高级)模拟考…...
伊朗相关的OilRig组织在为期8个月的网络攻击中针对中东政府
导语 伊朗相关的OilRig组织最近在中东政府中展开了一场长达8个月的网络攻击行动。这次攻击导致了文件和密码的被窃取,并且在其中一次攻击中,攻击者还使用了一种名为PowerExchange的PowerShell后门。据Symantec的威胁猎人团队称,他们在一份与T…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
