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.mzph.cn/news/895166.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【语法】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…

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…

【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;能够提供一…

windows通过网络向Ubuntu发送文件/目录

由于最近要使用树莓派进行一些代码练习&#xff0c;但是好多东西都在windows里或虚拟机上&#xff0c;就想将文件传输到树莓派上&#xff0c;但试了发现u盘不能简单传送&#xff0c;就在网络上找到了通过windows 的scp命令传送 前提是树莓派先开启ssh服务&#xff0c;且Window…

字节跳动后端一面

&#x1f4cd;1. Gzip压缩技术详解 Gzip是一种流行的无损数据压缩格式&#xff0c;它使用DEFLATE算法来减少文件大小&#xff0c;广泛应用于网络传输和文件存储中以提高效率。 &#x1f680; 使用场景&#xff1a; • 网站优化&#xff1a;通过压缩HTML、CSS、JavaScript文件来…

三维模拟-机械臂自翻车

机械仿真 前言效果图后续 前言 最近在研究Unity机械仿真&#xff0c;用Unity实现其运动学仿真展示的功能&#xff0c;发现一个好用的插件“MGS-Machinery-master”&#xff0c;完美的解决了Unity关节定义缺少液压缸伸缩关节功能&#xff0c;内置了多个场景&#xff0c;讲真的&…

USB子系统学习(四)用户态下使用libusb读取鼠标数据

文章目录 1、声明2、HID协议2.1、描述符2.2、鼠标数据格式 3、应用程序4、编译应用程序5、测试6、其它 1、声明 本文是在学习韦东山《驱动大全》USB子系统时&#xff0c;为梳理知识点和自己回看而记录&#xff0c;全部内容高度复制粘贴。 韦老师的《驱动大全》&#xff1a;商…

史上最快 Python版本 Python 3.13 安装教程

Python3.13安装和配置 一、Python的下载 1. 网盘下载地址 (下载速度比较快&#xff0c;推荐&#xff09; Python3.13.0下载&#xff1a;Python3.13.0下载地址&#xff08;windows&#xff09;3.13.0下载地址&#xff08;windows&#xff09; 点击下面的下载链接&#xff0c…

AWS Fargate

AWS Fargate 是一个由 Amazon Web Services (AWS) 提供的无服务器容器计算引擎。它使开发者能够运行容器化应用程序&#xff0c;而无需管理底层的服务器或虚拟机。简而言之&#xff0c;AWS Fargate 让你只需关注应用的容器本身&#xff0c;而不需要管理运行容器的基础设施&…

vue3+vite+eslint|prettier+elementplus+国际化+axios封装+pinia

文章目录 vue3 vite 创建项目如果创建项目选了 eslint prettier从零教你使用 eslint prettier第一步&#xff0c;下载eslint第二步&#xff0c;创建eslint配置文件&#xff0c;并下载好其他插件第三步&#xff1a;安装 prettier安装后配置 eslint (2025/2/7 补充) 第四步&am…

vLLM V1 重磅升级:核心架构全面革新

本文主要是 翻译简化个人评读&#xff0c;原文请参考&#xff1a;vLLM V1: A Major Upgrade to vLLM’s Core Architecture vLLM V1 开发背景 2025年1月27日&#xff0c;vLLM 开发团队推出 vLLM V1 alpha 版本&#xff0c;这是对框架核心架构的里程碑式升级。基于过去一年半的…