里氏替換原則(LSP)

太好了,現在我們來講解 SOLID 中非常核心的 LSP:里氏替換原則(Liskov Substitution Principle)

我會一步步講清楚:

  • 什么是 LSP?
  • 為什么重要?
  • 優劣分析
  • Python 正反例子
  • 清晰的結構圖(Mermaid)

🧠 一句話定義(LSP)

任何父類出現的地方,都應該可以用它的子類替代,并且不會導致程序邏輯出錯。

簡化記憶:

子類能替換父類,并保持行為正確。


🎯 為什么需要?

當你用多態寫程序(比如用父類來調用子類對象)時:

如果子類違背了父類的行為約定,會導致系統運行時出現不符合預期的錯誤,就違反了 LSP


? 優點 vs ? 缺點

優點缺點
子類更符合父類語義設計成本提升
多態行為更安全有時限制了子類個性
程序行為更穩定實現復雜邏輯更麻煩

🔥 常見違反 LSP 的坑

子類復寫方法后,行為和父類完全不同、甚至反邏輯。


? 違反 LSP 的反面例子

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 的正確做法(更合理抽象)

from abc import ABC, abstractmethod# 抽象出“會飛的鳥”和“不飛的鳥”
class Bird(ABC):@abstractmethoddef eat(self):passclass Flyable(ABC):@abstractmethoddef fly(self):passclass 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 嗎?實戰會更直觀哦。你想繼續擴展哪部分?🔍

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904019.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904019.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904019.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

skynet.socket.limit 使用詳解

目錄 核心作用方法定義使用場景場景 1:限制接收緩沖區(防御大包攻擊)場景 2:動態調整限制(應對不同負載) 底層機制注意事項完整示例:帶流量控制的 Echo 服務總結 在 Skynet 框架中,s…

算法每日一題 | 入門-順序結構-數字反轉

數字反轉 題目描述 輸入一個不小于 且小于 ,同時包括小數點后一位的一個浮點數,例如 ,要求把這個數字翻轉過來,變成 并輸出。 輸入格式 一行一個浮點數 輸出格式 一行一個浮點數 輸入輸出樣例 #1 輸入 #1 123.4輸出 #1 …

數據庫數據去重常用方式

數據庫數據去重是一個常見的操作,常用的方式包擇包括: 使用 DISTINCT 關鍵字:在查詢數據時,可以使用 SELECT DISTINCT 來去除結果集中的重復數據。 使用 GROUP BY 語句:可以使用 GROUP BY 子句來對結果進行分組&#…

快樂數(簡單)

代碼&#xff1a; import java.util.HashSet; import java.util.Set;class Solution {public boolean isHappy(int n) {Set<Integer> seen new HashSet<>();while (n ! 1 && !seen.contains(n)) {seen.add(n);n getNext(n);}return n 1;}private int g…

Linux操作系統從入門到實戰(五)詳細講解Linux權限概念

Linux操作系統從入門到實戰&#xff08;五&#xff09;詳細講解Linux權限概念 前言一、Linux中兩種用戶1.1 超級用戶&#xff08;root&#xff09;1.2 普通用戶1.3 切換用戶命令 二、Linux權限管理2.1 文件訪問者的分類&#xff1a;誰能訪問文件&#xff1f;2.2 文件類型2.3 基…

91.首次使用Maui的體驗與建議 C#例子 Maui例子

最近我開始接觸Maui&#xff0c;記錄一下我的首次使用體驗&#xff0c;希望能給大家提供一些參考。 安裝與創建項目 首次接觸Maui&#xff0c;其實遇到了不少疑惑。首先&#xff0c;通過Visual Studio的安裝器安裝Maui開發環境。安裝過程還算順利&#xff0c;但需要注意的是&…

【家政平臺開發(100)】終結篇,破局·拓新:家政平臺未來發展的戰略藍圖

本【家政平臺開發】專欄聚焦家政平臺從 0 到 1 的全流程打造。從前期需求分析,剖析家政行業現狀、挖掘用戶需求與梳理功能要點,到系統設計階段的架構選型、數據庫構建,再到開發階段各模塊逐一實現。涵蓋移動與 PC 端設計、接口開發及性能優化,測試階段多維度保障平臺質量,…

小程序滾動條隱藏(uniapp版本)

單獨指定頁面隱藏&#xff08;找到對應的scroll-view&#xff09; <style> /* 全局隱藏滾動條樣式 */ ::-webkit-scrollbar { display: none; width: 0; height: 0; color: transparent; background: transparent; } /* 確保scroll-view組件也隱藏滾動條 */ …

5月3日日記

上午睡到自然醒&#xff08;其實六點多被我爸叫起來搶火車票&#xff0c;發現明天中午的軟臥候補上了&#xff0c;挺好的&#xff09;然后繼續睡到快10點。 中午吃的什么來著&#xff0c;好像是西紅柿炒雞蛋和藜麥飯&#xff0c;有個魚不是很想吃就沒吃 中午打了兩把吃雞&…

【Spring】Spring中8種常見依賴注入使用示例

在 Spring 中&#xff0c;IoC 注入可以通過多種方式實現&#xff0c;涵蓋不同場景的依賴管理。以下是 8 種常見場景的詳細示例及說明&#xff0c;結合 XML、注解和 Java 配置類三種方式。 1. 構造器注入&#xff08;推薦方式&#xff09; 通過構造器傳遞依賴&#xff0c;確保對…

藍橋杯 擺動序列

擺動序列 原題目鏈接 題目描述 如果一個序列的奇數項都比前一項大&#xff0c;偶數項都比前一項小&#xff0c;則稱為一個擺動序列。 即對于任意整數 i&#xff08;i ≥ 1&#xff09;滿足&#xff1a; a?? < a????&#xff0c;a???? > a?? 小明想知道&…

REINFORCE蒙特卡羅策略梯度算法詳解:python從零實現

&#x1f9e0; 向所有學習者致敬&#xff01; “學習不是裝滿一桶水&#xff0c;而是點燃一把火。” —— 葉芝 我的博客主頁&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 歡迎點擊加入AI人工智能社區&#xff01; &#x1f680; 讓我們一起努力&#xff0c;共創…

深入了解Linux系統—— 操作系統

一、馮諾依曼體系結構 現在我們常見的計算機&#xff08;筆記本電腦等&#xff09;和不常見的計算機&#xff08;服務器&#xff09;它們都滿足馮諾依曼體系。 我們可以把計算機理解成一個個硬件組成的 輸入設備&#xff1a;鍵盤、鼠標、攝像頭、網卡、磁盤等輸出設備&#xf…

RPG7.準備GAS的工作

1.啟動項目&#xff0c;為項目添加gameplayability插件 2.添加abilitysystemcomponent的c類 3.添加attributeset的c類 4.往build.cs內添加模塊 5.進入CharacterBase內&#xff0c;添加gameplayasystem和attributbeset&#xff0c;覆寫PossessedBy()和GetAbilitysystemcomponent…

使用gitea發布軟件包

1、新建hello工程 &#xff08;1&#xff09;HelloApplication.java package cn.ac.trimps.sv;import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplicati…

從請求到響應:初探spring web

引入&#xff1a; 首先小編想分享下一些開發小知識 2000年——手寫servlet/JSP時代 在這個階段中&#xff0c;那時候寫后端代碼&#xff0c;可謂是個麻煩事。 畢竟什么都要自己干 發來的請求都要寫extends HttpServlet的類&#xff0c;手動在web.xml配置 <servlet>…

Redis從入門到實戰實戰篇2

面試重點&#xff1a;本篇包含悲觀鎖&#xff0c;樂觀鎖&#xff0c;多線程以及分布式鎖的知識 目錄 3.優惠卷秒殺 3.1 -全局唯一ID 3.2 -Redis實現全局唯一Id 3.3 添加優惠卷 3.4 實現秒殺下單 3.5 庫存超賣問題分析 3.6 樂觀鎖解決超賣問題 3.7 優惠券秒殺-一人一單 …

LabVIEW實驗室項目中使用類模塊與仿真

在 LabVIEW 程序開發過程中&#xff0c;借鑒面向對象的類思想進行模塊化架構設計&#xff0c;并結合仿真功能&#xff0c;能夠高效應對不同場景的開發需求。 ? 以實驗室場景為例&#xff0c;LabVIEW 開發常面臨設備種類繁多、調試周期漫長&#xff0c;且硬件難以一次性到位的情…

ES6入門---第二單元 模塊三:對象新增、

一&#xff1a;對象簡潔語法&#xff1a; 1、變量簡潔 <script>let name Strive;let age 18;let json {name, //name:name,age //age:age};console.log(json);</script> 2、函數簡潔 let json {name, //name:name,age, //age:age/* showA:functi…

Python創意:AI圖像生成——用代碼繪制未來藝術

當代碼邂逅藝術:AI圖像生成的革命 在數字藝術領域,一場由Python和AI技術引領的革命正在悄然發生。無需專業繪畫技巧,僅憑幾行代碼,普通人也能創造出令人驚嘆的藝術作品。AI圖像生成技術打破了藝術創作的門檻,讓想象力成為唯一的限制。 核心技術方案 1. 技術架構 我們采…