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

Java设计模式—面向对象设计原则(二) --------> 里氏代换原则 LSP (完整详解,附有代码+案列)

文章目录

    • 里氏代换原则
      • 3.2.1 概述
      • 3.2.2 改进上述代码

里氏代换原则

里氏代换原则:Liskov Substitution Principle,LSP

3.2.1 概述

里氏代换原则是面向对象设计的基本原则之一。

  • 里氏代换原则:任何基类可以出现的地方,子类一定可以出现。通俗理解:子类可以扩展父类的功能,但不能改变父类原有的功能。换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。
  • 如果通过重写父类的方法来完成新的功能,写起来虽然简单,但整个继承体系的可复用性会比较差,特别是运用多态比较频繁时,程序运行出错的概率会非常大。

下面看一个里氏替换原则中经典的一个反例:

【例】正方形不是长方形。

  • 在数学领域里,正方形毫无疑问是长方形,它是一个长宽相等的长方形。所以,我们开发的一个与几何图形相关的软件系统,就可以顺理成章的让正方形继承自长方形。

在这里插入图片描述

代码如下:

//父类  长方形
public class Rectangle {private double length;private double width;public double getLength() {return length; }public void setLength(double length) {this.length = length;}public double getWidth() { return width;}public void setWidth(double width) {this.width = width;}
}
======================================================
//子类(正方形) 继承父类(长方形)
//由于正方形的长和宽相同,所以在方法setLength和setWidth中,对长度和宽度都需要赋相同值。public class Square  extends Rectangle{// 重写父类中的方法@Overridepublic void setLength(double length) {super.setLength(length);super.setWidth(length);}// 重写父类中的方法@Overridepublic void setWidth(double width) {super.setWidth(width);super.setLength(width);}
}
======================================================
//测试类public class Test01 {public static void main(String[] args) {// 创建长方形对象Rectangle r = new Rectangle();// 设置长宽r.setWidth(6);r.setLength(8);// 扩宽方法resize(r);// 打印扩宽后的长和宽printLengthWidth(r);//8.0 , 9.0//====以下演示 违背里氏代换原则的效果====// 创建正方形对象Square s = new Square();// 设置正方形的长或者宽s.setLength(8);//resize()方法中的形参是父类类型,所以可以传递子类的类型//是多态形式resize(s);printLengthWidth(s);//执行到这里会死循环,知道内存溢出才停止//所以根据里氏代换原则:任何基类可以出现的地方,子类一定可以出现//但尽量不要重写父类的方法,如果重写会程序会出问题,比如此处的死循环}//扩宽方法public static void resize(Rectangle r){//判断宽如果比长小,进行扩宽的操作while (r.getWidth() <= r.getLength()){r.setWidth(r.getWidth() + 1);}}//打印长和宽public static void printLengthWidth(Rectangle r){System.out.println(r.getLength());System.out.println(r.getWidth());}
}
  • 运行上述段代码发现,假如把一个普通长方形作为参数传入resize方法,就会看到长方形宽度逐渐增长的效果,当宽度大于长度,代码就会停止,这种行为的结果符合我们的预期;假如再把一个正方形作为参数传入resize方法后,就会看到正方形的宽度和长度都在不断增长,代码会一直运行下去,直至系统产生溢出错误。所以,普通的长方形是适合这段代码的,正方形不适合。
  • 得出结论:在resize方法中,Rectangle类型的参数是不能被Square类型的参数所代替,如果进行了替换就得不到预期结果。因此,Square类和Rectangle类之间的继承关系违反了里氏代换原则(即任何基类可以出现的地方,子类一定可以出现),它们之间的继承关系不成立,正方形不是长方形。

3.2.2 改进上述代码

在这里插入图片描述

//四边形接口类
public interface Quadrilateral {public abstract double getLength();public abstract double getWidth();
}
==========================================================// 长方形类 实现四边形接口
public class Rectangle implements Quadrilateral{private double length;private double width;public void setLength(double length) {this.length = length;}public void setWidth(double width) {this.width = width;}@Overridepublic double getLength() {return length;}@Overridepublic double getWidth() {return width;}
}
============================================================// 正方形类   实现四边形接口
public class Square implements Quadrilateral {private double side;public double getSide() {return side;}public void setSide(double side) {this.side = side;}@Overridepublic double getLength() {return side;}@Overridepublic double getWidth() {return side;}
}
==========================================================public class Test {public static void main(String[] args) {// 创建长方形对象Rectangle r = new Rectangle();r.setLength(20);r.setWidth(19);resize(r);printLengthAndWidth(r);// 创建正方形对象Square s = new Square();// resize(s);此行编译错误//因为正方形和长方形已经没有直接关系printLengthAndWidth(s);}//扩宽方法public static void resize(Rectangle r){//判断宽如果比长小,进行扩宽的操作while (r.getWidth() <= r.getLength()){r.setWidth(r.getWidth() + 1);}}//打印长和宽   接口多态public static void printLengthAndWidth(Quadrilateral q) {System.out.println(q.getLength());System.out.println(q.getWidth());}
}

相关文章:

Java设计模式—面向对象设计原则(二) --------> 里氏代换原则 LSP (完整详解,附有代码+案列)

文章目录 里氏代换原则3.2.1 概述3.2.2 改进上述代码 里氏代换原则 里氏代换原则&#xff1a;Liskov Substitution Principle&#xff0c;LSP 3.2.1 概述 里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则&#xff1a;任何基类可以出现的地方&#xff0c;子类一定…...

使用ShardingSphere实现MySql的分库分表

目录 一 什么是ShardingSphere分库分表 二 代码实现 1.导入相关依赖 2.配置相关参数 3.创建学生类以及mapper接口 4.实现 StandardShardingAlgorithm接口自定义分片算法 唐洋洋我知道你在看!!!嘿嘿 一 什么是ShardingSphere分库分表 我们平时在设计数据库的时候&#xf…...

为什么 Feign 要用 HTTP 而不是 RPC?

一、引言 在现代微服务架构中&#xff0c;服务之间的通信是至关重要的环节。Feign 是一种常用的声明式 HTTP 客户端工具&#xff0c;它简化了服务间的调用过程。然而&#xff0c;在服务通信的领域中&#xff0c;除了基于 HTTP 的方式&#xff0c;还有 RPC&#xff08;Remote Pr…...

OJ在线评测系统 前端开发设计优化通用菜单组件二 调试用户自动登录

通用的菜单组件开发二 接下来要完善 权限功能 就是只有登录后才能进入题目查看界面 用户只能看到我们有权限的菜单 我们要在路由文件里面去操作 原理是控制路由设置隐藏 只要用户没有权限 就过滤掉隐藏 全局权限管理 实现想清楚有那些权限 /*** 权限定义*/ const ACCES…...

mongodb 安装教程

mongodb 安装教程&#xff1a; https://blog.51cto.com/u_13646338/5449015 wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-5.0.9.tgz tar -zxvf mongodb-linux-x86_64-rhel70-5.0.9.tgz -C /opt/module/ [roothadoop102 module]# mv mongodb-linux-…...

切换淘宝最新镜像源npm

要切换淘宝的npm镜像源&#xff0c;可以按照以下步骤进行&#xff1a; 1. 打开命令行工具&#xff08;如Terminal、CMD等&#xff09;。 2. 输入以下命令来查看当前的npm镜像源&#xff1a; npm config get registry 3. 如果当前的镜像源不是淘宝镜像源&#xff…...

SpringAI-基于java大模型的胡言乱语

最近看了一点相关的springAI知识&#xff0c;做个小总结 胡言乱语开始 1.不同的ai调用api一般单独汇总成一个依赖&#xff0c;比如说调用openai的api的依赖是spring-ai-openai-spring-boot-starter。 2.最常用的展示方式是流式对话&#xff0c;AI的数据是一个字一个字生成的…...

python提问及解析

在看答案之前&#xff0c;可以先试试自己做哦&#xff01; 1.图书馆借书还书系统 问题描述 问题&#xff1a;设计一个Python程序&#xff0c;该程序模拟一个大型图书馆的图书管理系统。图书馆拥有成千上万的书籍&#xff0c;每本书都有一个唯一的ISBN号、书名、作者、出版年份…...

从Apple Intelligence到IoT Intelligence,端侧生成式AI时代加速到来

9月10日凌晨1点&#xff0c;苹果新品发布会如期举行&#xff0c;全新iPhone16系列成为苹果生态中真正意义上的第一款原生AI手机&#xff0c;在第二代3nm工艺A18和A18 Pro芯片的加持下&#xff0c;iPhone16系列能够容纳并快速运行以Apple Intelligence为中心的生成式AI功能在手机…...

智能AC管理系统HTTPD-AC 1.0服务存在未授权访问漏洞

@[toc] 智能AC管理系统HTTPD-AC 1.0服务存在未授权访问漏洞 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途…...

Sidewalk介绍

目录 1 前言2 简介2.1 注意事项 3 结束语 1 前言 Sidewalk是Amazon出的一个针对IoT物联网的协议&#xff0c;类似于LoRaWAN协议&#xff0c;针对小而美的低功耗设备。Amazon Sidewalk支持低带宽和远程连接&#xff0c;使用BLE进行短距离通信&#xff0c;使用900MHz的频率的LoR…...

Java数据结构 (泛型第二节) 泛型擦除机制/泛型的限制/上界下界

书接上回&#xff1a;Java数据结构 (泛型第一节) 为什么要有泛型/泛型语法/泛型方法-CSDN博客 访问作者Github: https://github.com/Joeysoda/Github_java/blob/main/20240908%E6%B3%9B%E5%9E%8B/src/%E6%B3%9B%E5%9E%8B.java 目录 1. 为什么要有擦除机制&#xff1f; 2. 类…...

数据安全标准在非结构化数据中台的遵守

在数字化转型的浪潮中&#xff0c;非结构化数据中台作为企业数据管理的核心枢纽&#xff0c;承载着海量且多样的数据资产。这些数据不仅关乎企业的运营决策&#xff0c;更涉及客户隐私、商业机密等敏感信息。因此&#xff0c;确保非结构化数据中台遵守数据安全标准&#xff0c;…...

探索Go语言中的Goroutine并发机制

什么是Goroutine 在Go语言中,Goroutine 是程序中最基本的并发单位。事实上,每个Go程序都会自动创建一个goroutine,那就是主goroutine,程序启动时会立即执行。Goroutine是Go语言中处理并发问题的核心工具,因此理解它的工作原理至关重要。 简而言之,Goroutine是并发执行的…...

实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??

文章目录 短轮询&#xff08;Short Polling&#xff09;长轮询&#xff08;Long Polling&#xff09;Comet “服务器推” &#xff08;这玩意现在用的很少了&#xff0c;了解一下即可&#xff09;WebSocket原理&#xff1a;方法&#xff1a;事件&#xff1a; SSE原理事件 总结 …...

3GPP协议入门——物理层基础(一)

1. 频段/带宽 NR指定了两个频率范围&#xff0c;FR1&#xff1a;通常称Sub 6GHz&#xff0c;也称低频5G&#xff1b;FR2&#xff1a;通常称毫米波&#xff08;Millimeter Wave&#xff09;&#xff0c;也称高频5G。 2. 子载波间隔 NR中有15kHz&#xff0c;30kHz&#xff0c;6…...

关于Java数据结构中集合的一个小知识

在我们以后刷题的过程&#xff0c;我们会遇到一些奇怪的集合数据类型。 如下图 这里&#xff0c;我们以顺序表的集合类为例&#xff0c;我们看到上图函数的返回值类型有点奇怪&#xff0c;其实并不奇怪&#xff0c;也就是穿过去的参数类型是一个顺序表的集合类型&#xff0c;也…...

leetcode41. 缺失的第一个正数,原地哈希表

leetcode41. 缺失的第一个正数 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xf…...

如何准备教师资格证科目三“学科知识与教学能力”的考试与面试?(理科导向:数学/物理)

如何准备教师资格证科目三“学科知识与教学能力”的考试与面试&#xff1f;&#xff08;理科导向&#xff1a;数学/物理&#xff09; ​ 目录 收起 1 前言 1.1 自身经历 1.2 教师资格证的作用 2 知识点题型分数的分布与学习建议 2.1 科目三的知识点分数分布&#xff1a; …...

3.数据类型

作业系统链接 Python 是一门面向对象友好的语言&#xff0c;支持多种内置数据类型&#xff0c;包括整数&#xff08;int&#xff09;、浮点数&#xff08;float&#xff09;、布尔值&#xff08;bool&#xff09;、字符串&#xff08;str&#xff09;、列表&#xff08;list&am…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...

【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析

1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器&#xff08;TI&#xff09;推出的一款 汽车级同步降压转换器&#xff08;DC-DC开关稳压器&#xff09;&#xff0c;属于高性能电源管理芯片。核心特性包括&#xff1a; 输入电压范围&#xff1a;2.95V–6V&#xff0c;输…...