Swift的方法派發機制

1. 靜態派發(Static Dispatch)

靜態派發在編譯時確定方法的具體實現,調用時直接跳轉到該實現。靜態派發的優點是性能高,因為不需要運行時查找方法實現。

適用場景:
  • 值類型(Struct 和 Enum):值類型的方法默認使用靜態派發。

  • Final 類和方法:標記為?final?的類或方法無法被繼承或重寫,因此使用靜態派發。

  • 全局函數和靜態方法:這些方法在編譯時就能確定實現,使用靜態派發。

示例:
struct Point {var x: Intvar y: Intfunc description() -> String {return "(\(x), \(y))"}
}let p = Point(x: 10, y: 20)
print(p.description())  // 靜態派發

2. 動態派發(Dynamic Dispatch)

動態派發在運行時確定方法的具體實現。Swift 中的動態派發主要通過虛表(VTable)和消息轉發(Message Forwarding)實現。

2.1 虛表派發(VTable Dispatch)

虛表派發是類方法默認的派發方式。每個類都有一個虛表,其中存儲了該類所有可重寫方法的指針。子類繼承父類的虛表,并可以覆蓋其中的方法指針。

適用場景:
  • 類的非 Final 方法:類的方法默認使用虛表派發,除非標記為?final

  • 繼承和重寫:子類可以重寫父類的方法,運行時根據對象的實際類型調用正確的方法。

示例:
class Animal {func makeSound() {print("Some sound")}
}class Dog: Animal {override func makeSound() {print("Bark")}
}let animal: Animal = Dog()
animal.makeSound()  // 動態派發,輸出 "Bark"
2.2 消息轉發(Message Forwarding)

消息轉發是 Objective-C 的派發機制,Swift 通過?@objc?和?dynamic?關鍵字支持這種派發方式。消息轉發允許在運行時動態解析方法調用,甚至可以在運行時修改方法實現。

適用場景:
  • 與 Objective-C 交互:標記為?@objc?的方法使用消息轉發。

  • 動態方法解析:標記為?dynamic?的方法使用消息轉發,允許在運行時修改方法實現。

示例:
class MyClass {@objc dynamic func sayHello() {print("Hello")}
}let instance = MyClass()
instance.sayHello()  // 消息轉發

3. 協議派發(Protocol Witness Table Dispatch)

協議方法使用協議見證表(Protocol Witness Table, PWT)進行派發。每個遵循協議的類型都有一個 PWT,其中存儲了協議方法的實現指針。

適用場景:
  • 協議方法:協議中的方法默認使用 PWT 派發。

  • 泛型約束:泛型類型約束為協議時,使用 PWT 派發。

示例:
protocol Greetable {func greet()
}struct Person: Greetable {func greet() {print("Hello")}
}let greeter: Greetable = Person()
greeter.greet()  // 協議派發

4. 特殊場景

4.1 泛型方法派發

泛型方法在編譯時生成特定類型的實現,通常使用靜態派發。但如果泛型類型約束為協議,則使用協議派發。

示例:
func printGreeting<T: Greetable>(_ greeter: T) {greeter.greet()  // 協議派發
}let person = Person()
printGreeting(person)  // 輸出 "Hello"
4.2 擴展中的方法派發

擴展中的方法默認使用靜態派發,即使是對類類型的擴展。如果擴展中的方法被重寫,仍然使用靜態派發。

示例:
class MyClass {func sayHello() {print("Hello from MyClass")}
}extension MyClass {func sayGoodbye() {print("Goodbye from MyClass")}
}class SubClass: MyClass {override func sayHello() {print("Hello from SubClass")}// 無法重寫擴展中的方法
}let instance: MyClass = SubClass()
instance.sayHello()  // 動態派發,輸出 "Hello from SubClass"
instance.sayGoodbye()  // 靜態派發,輸出 "Goodbye from MyClass"
4.3?@objc?和?dynamic?方法

標記為?@objc?的方法使用消息轉發,允許與 Objective-C 交互。標記為?dynamic?的方法也使用消息轉發,允許在運行時修改方法實現。

示例:
class MyClass {@objc dynamic func sayHello() {print("Hello")}
}let instance = MyClass()
instance.sayHello()  // 消息轉發
4.4?final?關鍵字

標記為?final?的類或方法無法被繼承或重寫,因此使用靜態派發。

示例:
final class MyFinalClass {func sayHello() {print("Hello")}
}let instance = MyFinalClass()
instance.sayHello()  // 靜態派發

總結

Swift 的方法派發機制靈活且高效,支持多種派發方式以適應不同的場景:

  • 靜態派發:適用于值類型、Final 類和方法,性能最高。

  • 動態派發:適用于類的繼承和重寫,通過虛表派發。

  • 協議派發:適用于協議方法,通過協議見證表派發。

  • 消息轉發:適用于與 Objective-C 交互和動態方法解析。

理解這些派發機制有助于編寫高效且符合預期的 Swift 代碼。

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

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

相關文章

C++并發編程指南 09(共享數據)

文章目錄 第3章 共享數據本章主要內容共享數據的問題使用互斥保護數據保護數據的替代方案 3.1 共享數據的問題共享數據的核心問題不變量的重要性示例&#xff1a;刪除雙鏈表中的節點多線程環境中的問題條件競爭的后果總結3.1.1 條件競爭3.1.2 避免惡性條件競爭 3.2 使用互斥量3…

ZooKeeper 技術全解:概念、功能、文件系統與主從同步

引言 隨著分布式系統變得越來越復雜&#xff0c;對協調服務的需求也在不斷增長。ZooKeeper 作為一個由 Apache 維護的開源分布式協調服務框架&#xff0c;廣泛用于 Hadoop 生態系統和其他需要協調的分布式環境中。這一系統旨在解決分布式應用中常見的挑戰&#xff0c;如配置管…

設計方案主要做哪些事情?

目錄 1. 需求分析 2. 系統架構設計 3. 數據庫設計 4. 接口設計 5. 緩存設計 6. 安全設計 7. 性能優化 8. 高可用與容災 9. 監控與日志 10. 測試方案 11. 部署方案 12. 文檔編寫 13. 風險評估 14. 項目管理 總結 設計方案是項目開發的關鍵步驟,確保項目按計劃進…

【語法】C++的內存管理 模板

內存管理&#xff1a; 在C語言中&#xff0c;動態開辟空間可以用malloc&#xff0c;calloc&#xff0c;realloc這三個函數&#xff0c;下面先來復習一下這三者的區別 malloc和calloc都是用來開辟新空間&#xff0c;calloc在malloc的基礎上還會初始化該空間為0&#xff0c;用法…

30~32.ppt

目錄 30.導游小姚-介紹首都北京? 題目? 解析 31.小張-旅游產品推廣文章 題目 解析 32.小李-水的知識? 題目? 解析 30.導游小姚-介紹首都北京? 題目 解析 新建幻燈片-從大綱-重置-檢查設計→主題對話框→瀏覽主題&#xff1a;考生文件夾&#xff08;注意&#x…

深度學習-交易預測

下面為你詳細介紹如何使用Python結合深度學習庫TensorFlow和Keras來構建一個簡單的交易預測模型。在這個示例中&#xff0c;我們以股票價格預測為例&#xff0c;假設我們要根據過去一段時間的股票價格數據來預測未來的價格走勢。 步驟分析 數據準備&#xff1a;獲取股票價格數…

C++ STL Map 學習學案(提高版)

C++ STL Map 學案(初中生版) 一、學習目標 深入理解 STL 中 map 容器的概念、特點和用途。熟練掌握 map 容器的基本操作,如插入、查找、刪除和遍歷元素。能夠運用 map 容器解決實際編程問題,提升邏輯思維和編程實踐能力。二、知識講解 引入 在日常生活中,我們常常會遇到…

uniapp實現人臉識別(不使用三方插件)

uniapp實現人臉識別 內容簡介功能實現上傳身份證進行人臉比對 遇到的問題 內容簡介 1.拍攝/相冊將身份證照片上傳到接口進行圖片解析 2.使用live-pusher組件拍攝人臉照片&#xff0c;上傳接口與身份證人臉進行比對 功能實現 上傳身份證 先看下效果 點擊按鈕調用chooseImage…

Evaluating Very Long-Term Conversational Memory of LLM Agents 論文

Abstract : 長期開放域對話的現有作品著重于評估不超過五個聊天會議的上下文中的模型響應。盡管LongContext大語言模型&#xff08;LLM&#xff09;和檢索增強發電&#xff08;RAG&#xff09;技術的進步&#xff0c;但在長期對話中的功效仍未得到探索。為了解決這一研究差距&a…

相對收益-固定收益組合歸因-Campisi模型

固定收益組合歸因-Campisi模型 1 Campisi模型11.1 Campisi歸因框架1.2 Campisi模型絕對收益分解1.2.1 票息收益1. 2.2 收斂收益1. 2.3 騎乘收益1. 2.4 平移收益1. 2.5 扭曲收益1. 2.6 利差收益1. 2.7 殘差收益 1.3 Campisi模型超額收益分解 2 Campisi模型22.1 分解框架2.2 模型…

IntelliJ IDEA使用經驗(十三):使用Git克隆github的開源項目

文章目錄 問題背景辦法1、設置git代理&#xff1b;2、再次克隆項目&#xff1b;3、再次按常規方式進行git克隆即可。 問題背景 由于github在國外&#xff0c;很多時候我們在使用idea克隆開源項目的時候&#xff0c;沒辦法檢出&#xff0c;提示 連接重置。 辦法 1、設置git代…

JAVA安全之Java Agent打內存馬

基本介紹 Java Agent是一種特殊的Java程序&#xff0c;它允許開發者在Java虛擬機(JVM)啟動時或運行期間通過java.lang.instrument包提供的Java標準接口進行代碼插樁&#xff0c;從而實現在Java應用程序類加載和運行期間動態修改已加載或者未加載的類&#xff0c;包括類的屬性、…

RabbitMQ 消息順序性保證

方式一&#xff1a;Consumer設置exclusive 注意條件 作用于basic.consume不支持quorum queue 當同時有A、B兩個消費者調用basic.consume方法消費&#xff0c;并將exclusive設置為true時&#xff0c;第二個消費者會拋出異常&#xff1a; com.rabbitmq.client.AlreadyClosedEx…

SQL自學,mysql從入門到精通 --- 第 14天,主鍵、外鍵的使用

1.主鍵 PRIMARY KEY 主鍵的使用 字段值不允許重復&#xff0c;且不允許賦NULL值 創建主鍵 rootmysqldb 10:11: [d1]> CREATE TABLE t3(-> name varchar(10) PRIMARY KEY,-> age int,-> class varchar(8)-> ); Query OK, 0 rows affected (0.01 sec)rootmys…

DeepSeek深度思考:客戶端(Android/iOS)架構設計指南

目標讀者&#xff1a;中高級開發者、架構師 適用場景&#xff1a;大型復雜應用開發、跨團隊協作、長期維護迭代 一、架構設計核心原則 1.模塊化&#xff08;Modularization&#xff09; 橫向拆分&#xff1a;按功能邊界劃分&#xff08;如登錄、支付、消息模塊&#xff09;縱向…

【MQ】Spring3 中 RabbitMQ 的使用與常見場景

一、初識 MQ 傳統的單體架構&#xff0c;分布式架構的同步調用里&#xff0c;無論是方法調用&#xff0c;還是 OpenFeign 難免會有以下問題&#xff1a; 擴展性差&#xff08;高耦合&#xff0c;需要依賴對應的服務&#xff0c;同樣的事件&#xff0c;不斷有新需求&#xff0…

EasyExcel 導出合并層級單元格

EasyExcel 導出合并層級單元格 一、案例 案例一 1.相同訂單號單元格進行合并 合并結果 案例二 1.相同訂單號的單元格進行合并2.相同訂單號的總數和總金額進行合并 合并結果 案例三 1.相同訂單號的單元格進行合并2.相同訂單號的商品分類進行合并3.相同訂單號的總數和總金額…

cs106x-lecture3(Autumn 2017)

打卡cs106x(Autumn 2017)-lecture3 1、streamErrors Suppose an input file named streamErrors-data.txt contains the following text: Donald Knuth M 76 Stanford U. The code below attempts to read the data from the file, but each section has a bug. Correct th…

C++模板編程——typelist的實現

文章最后給出了匯總的代碼&#xff0c;可直接運行 1. typelist是什么 typelist是一種用來操作類型的容器。和我們所熟知的vector、list、deque類似&#xff0c;只不過typelist存儲的不是變量&#xff0c;而是類型。 typelist簡單來說就是一個類型容器&#xff0c;能夠提供一…

springboot 事務管理

在Spring Boot中&#xff0c;事務管理是通過Spring框架的事務管理模塊來實現的。Spring提供了聲明式事務管理和編程式事務管理兩種方式。通常&#xff0c;我們使用聲明式事務管理&#xff0c;因為它更簡潔且易于維護。 1. 聲明式事務管理 聲明式事務管理是通過注解來實現的。…