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

Swift Protocols(协议)、Extensions(扩展)、Error Handling(错误处理)、Generics(泛型)

最近在学习 Swift,总结相关知识


1. Protocols(协议)

1.1 协议的定义和实现

  • 协议(protocol 是一种定义方法和属性的蓝图,任何类、结构体或枚举都可以遵循协议。
  • 遵循协议后,需要实现协议中定义的所有内容。
示例
protocol ExampleProtocol {var simpleDescription: String { get }mutating func adjust()
}
  • simpleDescription 定义了一个只读属性。
  • mutating 标记方法可以修改遵循协议的值类型(如结构体、枚举)。
实现协议
  • 类(class 遵循协议:

    class SimpleClass: ExampleProtocol {var simpleDescription: String = "A very simple class."var anotherProperty: Int = 69105func adjust() {simpleDescription += " Now 100% adjusted."}
    }
    
    • 方法 adjust 可以直接修改属性,无需标记为 mutating
  • 结构体(struct 遵循协议:

    struct SimpleStructure: ExampleProtocol {var simpleDescription: String = "A simple structure"mutating func adjust() {simpleDescription += " (adjusted)"}
    }
    
    • mutating 必须添加,因为结构体是值类型,默认情况下,方法不能修改实例。

1.2 扩展协议要求

向协议 ExampleProtocol 添加新的要求:

protocol ExampleProtocol {var simpleDescription: String { get }mutating func adjust()func detailedDescription() -> String
}class SimpleClass: ExampleProtocol {var simpleDescription: String = "A very simple class."func adjust() {simpleDescription += " Now 100% adjusted."}func detailedDescription() -> String {return "This is \(simpleDescription)"}
}struct SimpleStructure: ExampleProtocol {var simpleDescription: String = "A simple structure"mutating func adjust() {simpleDescription += " (adjusted)"}func detailedDescription() -> String {return "This is \(simpleDescription)"}
}

2. Extensions(扩展)

2.1 扩展定义

扩展可以用来为现有的类、结构体、枚举或协议添加功能,例如添加方法、计算属性或协议一致性。

示例:扩展 Int
extension Int: ExampleProtocol {var simpleDescription: String {return "The number \(self)"}mutating func adjust() {self += 42}
}
print(7.simpleDescription) // 输出:The number 7
实验:扩展 Double 添加 absoluteValue
extension Double {var absoluteValue: Double {return self >= 0 ? self : -self}
}
print((-3.14).absoluteValue) // 输出:3.14

3. Error Handling(错误处理)

3.1 错误类型

  • Swift 的错误类型必须遵循 Error 协议,通常用 enum 定义。
enum PrinterError: Error {case outOfPapercase noTonercase onFire
}

3.2 抛出和捕获错误

  • 使用 throw 抛出错误,使用 throws 标记函数可能抛出错误。
  • 使用 do-catch 捕获错误。
示例
func send(job: Int, toPrinter printerName: String) throws -> String {if printerName == "Never Has Toner" {throw PrinterError.noToner}return "Job sent"
}do {let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")print(printerResponse)
} catch PrinterError.noToner {print("No toner available.")
} catch {print(error)
}

3.3 使用 try?defer

  • try? 抛出错误时返回 nil
  • defer 无论函数是否抛出错误,都执行清理代码。
示例
let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")func fridgeContains(_ food: String) -> Bool {defer { print("Fridge closed.") } // 确保清理return ["milk", "eggs"].contains(food)
}

4. Generics(泛型)

4.1 泛型函数

  • 泛型允许编写通用代码,支持多种类型。
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {var result: [Item] = []for _ in 0..<numberOfTimes {result.append(item)}return result
}
makeArray(repeating: "knock", numberOfTimes: 4)

4.2 泛型类型

  • 例如,重新实现 Swift 标准库的 Optional 类型:
enum OptionalValue<Wrapped> {case nonecase some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none
possibleInteger = .some(100)

4.3 泛型约束

  • 使用 where 指定类型约束。
func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Boolwhere T.Element: Equatable, T.Element == U.Element {for lhsItem in lhs {for rhsItem in rhs {if lhsItem == rhsItem {return true}}}return false
}
anyCommonElements([1, 2, 3], [3])
实验:返回公共元素数组
func commonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> [T.Element]where T.Element: Equatable, T.Element == U.Element {var result: [T.Element] = []for lhsItem in lhs {if rhs.contains(lhsItem) {result.append(lhsItem)}}return result
}
print(commonElements([1, 2, 3], [3, 4, 5])) // 输出:[3]

总结

Swift 提供了许多现代化特性:

  1. Protocols 和 Extensions: 提供灵活的功能扩展和一致性约束。
  2. Error Handling: 提供 throwdo-catchtry? 等灵活的错误处理机制。
  3. Generics: 支持编写通用、高效、类型安全的代码。
  4. 类型安全性: Swift 的类型系统可以有效防止运行时错误,提升代码可靠性。

相关文章:

Swift Protocols(协议)、Extensions(扩展)、Error Handling(错误处理)、Generics(泛型)

最近在学习 Swift&#xff0c;总结相关知识 1. Protocols&#xff08;协议&#xff09; 1.1 协议的定义和实现 协议&#xff08;protocol&#xff09; 是一种定义方法和属性的蓝图&#xff0c;任何类、结构体或枚举都可以遵循协议。遵循协议后&#xff0c;需要实现协议中定义…...

.NET中的强名称和签名机制

.NET中的强名称&#xff08;Strong Name&#xff09;和签名机制是.NET Framework引入的一种安全性和版本控制机制。以下是关于.NET中强名称和签名机制的详细解释&#xff1a; 强名称 定义&#xff1a; 强名称是由程序集的标识加上公钥和数字签名组成的。程序集的标识包括简单文…...

使用 NestJS 构建高效且模块化的 Node.js 应用程序,从安装到第一个 API 端点:一步一步指南

一、安装 NestJS 要开始构建一个基于 NestJS 的应用&#xff0c;首先需要安装一系列依赖包。以下是必要的安装命令&#xff1a; npm i --save nestjs/core nestjs/common rxjs reflect-metadata nestjs/platform-express npm install -g ts-node包名介绍nestjs/coreNestJS 框…...

2025年大模型技术发展趋势展望:高速旋转的飞轮

2025年大模型技术发展趋势展望 引言1. 多模态大模型&#xff08;MMM&#xff09;&#xff1a;从单一模态到高级模态融合2. 轻量化大模型&#xff1a;从大参数模型到小参数模型3. 强推理大模型&#xff1a;从概率生成到逻辑推理4. 移动端/边缘端Agent&#xff1a;从云端到本地5.…...

java中类的加载过程及各个阶段与运行时数据区中堆和方法区存储内容

java中类的加载过程 Java 类的加载是 JVM 将 字节码文件&#xff08;.class 文件&#xff09;加载到内存并最终转化为运行时数据的过程。它分为以下 五个主要阶段&#xff1a;加载、验证、准备、解析、初始化&#xff0c;每个阶段都有对应的内存位置存储相关信息。以下是类加载…...

渗透测试--Web基础漏洞利用技巧

渗透测试--Web基础漏洞利用技巧 本文章写了Web基础漏洞中一些不那么常见的利用技巧&#xff0c;而不谈及漏洞的原理以及常见用法。 SQL 俺是SQLmap党&#xff0c;哈哈&#xff0c;所以这块就不多讲了。详情可见文章《渗透测试--SQLmap_渗透测试sqlmap-CSDN博客》 XXE XXE组成…...

SpringBoot下载文件的几种方式

小文件&#xff1a;直接将文件一次性读取到内存中&#xff0c;文件大可能会导致OOM GetMapping("/download1")public void download1(HttpServletResponse response) throws IOException {// 指定要下载的文件File file new File("C:\\Users\\syd\\Desktop\\do…...

教程:从pycharm基于anaconda构建机器学习环境并运行第一个 Python 文件

1. 安装 PyCharm 访问 PyCharm 官方网站&#xff1a;https://www.jetbrains.com/pycharm/。下载社区版&#xff08;免费&#xff09;或专业版&#xff08;收费&#xff0c;提供更多功能&#xff09;。按照操作系统的安装指导安装 PyCharm。安装后打开 PyCharm&#xff0c;并根…...

我用Ai学Android Jetpack Compose之Button

答案来自 通义千问&#xff0c;代码同样需要到Android Studio里实践&#xff0c;才能学会。完整工程代码见文末。 我要学Button&#xff0c;麻烦介绍一下 当然可以&#xff01;Button 是 Jetpack Compose 中用于创建可点击按钮的 Composable 函数。它提供了丰富的配置选项来定…...

修改secure-file-priv参数-mysql5.7.26限制不允许导入或导出的解决方法

文章目录 前言secure_file_priv参数说明修改secure_file_priv参数的步骤 前言 本人是在sql注入的文件上传拿web shel 时所用到的写入文件权限遇到文件上传不成功的问题&#xff0c;记住修改后&#xff0c;重启mysql才生效&#xff0c;最后可以查看验证一下。 secure_file_priv…...

C# 设计模式(结构型模式):适配器模式

C# 设计模式&#xff08;结构型模式&#xff09;&#xff1a;适配器模式 在软件开发中&#xff0c;我们经常会遇到需要将不同接口的组件结合在一起的情况。此时&#xff0c;适配器模式&#xff08;Adapter Pattern&#xff09;就派上了用场。它属于结构型设计模式&#xff0c;…...

Spring Cloud微服务多模块架构:父子工程搭建实践

一、前言 在现代微服务架构中&#xff0c;Spring Cloud 提供了一整套工具和技术栈来简化分布式系统的开发。为了更好地组织和管理复杂的微服务项目&#xff0c;使用 Maven 多模块&#xff08;父子工程&#xff09; 是一种高效的方法。 ‍ 父子工程 是 Maven 中的一种项目结构…...

SkinnedMeshRenderer相关知识

SkinnedMeshRenderer和MeshRenderer unity中SkinnedMeshRenderer是CPU去更改顶点位置的。 而当使用MeshRenderer时&#xff0c;可以靠GPU来进行蒙皮&#xff08;即更改顶点位置&#xff09;。 SkinnedMeshRenderer是多线程处理的&#xff0c;在小程序游戏中&#xff0c;只支持…...

前端学习DAY30(水平)

子元素是在父元素的内容区中排列的&#xff0c;如果子元素的大小超过了父元素&#xff0c;则子元素会从 父元素中溢出&#xff0c;使用overflow属性设置父元素如何处理溢出的子元素 可选值&#xff1a;visible 默认值&#xff0c;子元素会从父元素中溢出&#xff0c;在父元素外…...

Spring boot 项目 Spring 注入 代理 并支持 代理对象使用 @Autowired 去调用其他服务

文章目录 类定义与依赖注入方法解析createCglibProxy注意事项setApplicationContext 方法createCglibProxy 方法 类定义与依赖注入 Service: 标识这是一个 Spring 管理的服务类。ApplicationContextAware: 实现该接口允许你在类中获取 ApplicationContext 对象&#xff0c;从而…...

Colyseus 与 HTTP API 的集成

Colyseus 与 HTTP API 的集成 在使用 Colyseus 开发实时多人应用时&#xff0c;通常需要与传统的 HTTP API 集成&#xff0c;例如用户身份验证、存储游戏数据、获取排行榜等。以下是 Colyseus 与 HTTP API 集成的详细介绍&#xff1a; 1. Colyseus 的基本架构 Colyseus 是一个…...

基于服务器部署的综合视频安防系统的智慧快消开源了。

智慧快消视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。国产化人工智能“…...

SpringBoot原理分析-1

SpringBoot原理分析 作为一个javaer&#xff0c;和boot打交道是很常见的吧。熟悉boot的人都会知道&#xff0c;启动一个springboot应用&#xff0c;就是用鼠标点一下启动main方法&#xff0c;然后等着就行了。我们来看看这个main里面。 SpringBootApplication public class E…...

HCIA-Access V2.5_7_5_XG(S)- GPON网络演进为XG(S)-PON网络

目前由于10 GPON ONU数量并没有得到大规模爆发,所以直接新建ODN网络成本相对较高,所以可以采用复用ODN的方案。 XG(S)-PON可以与GPON共享ODN 前面也介绍过GPON和10G GPON使用的波长,我们来回顾一下,在GPON网络中上行采用1310纳米波长,下行采用1490纳米的波长,而10G GPON…...

GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程

大家好&#xff0c;今天给大家介绍一下&#xff1a;GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程。 文章目录 一、GPU算力平台概述人工智能智能发展为什么需要GPU算力平台 二、注册与登录账号注册流程 三、平台的应用之Anydoor应用启动器选择Anydoor的应用场景Anydoo…...

西门子PLC伺服大型多轴多气缸智能控制,Modbus与RS232通讯,完整触摸屏程序,机械结构...

西门子PLC伺服大型20轴程序modbus通讯RS232通讯MES通讯气缸&#xff0c;通讯&#xff0c;机械手&#xff0c;模拟量等&#xff0c;各种FB块 PTO控制20多个轴&#xff0c;100多个气缸&#xff0c;控制2台机器人。 5台PLC智能IO通讯&#xff0c;ModbusRTU通讯轮询&#xff0c;完整…...

代码生成不再“盲写”:如何用搜索增强的AI编码工具提升47%开发效率?

第一章&#xff1a;代码生成不再“盲写”&#xff1a;如何用搜索增强的AI编码工具提升47%开发效率&#xff1f; 2026奇点智能技术大会(https://ml-summit.org) 传统AI编程助手常受限于上下文窗口与静态训练数据&#xff0c;面对新框架、私有API或内部SDK时容易“幻觉”输出不可…...

别再纠结了!MySQL和PostgreSQL到底怎么选?从CPU核数到索引类型,一次给你讲透

MySQL与PostgreSQL技术选型指南&#xff1a;从架构差异到业务场景适配 当项目面临数据库选型时&#xff0c;技术决策者常常陷入两难境地。作为开源关系型数据库的双雄&#xff0c;MySQL和PostgreSQL各有拥趸&#xff0c;但真正的专业选择应当基于客观的技术特性和实际业务需求。…...

STM32F429 HAL库 DMA方式实现SD卡高效存储.csv数据

1. 为什么需要DMA方式存储.csv数据 当你用STM32F429做数据采集时&#xff0c;最头疼的就是CPU被数据传输占满的问题。我去年做工业传感器项目时就遇到过——采集10个通道的模拟量数据&#xff0c;还要实时计算和存储&#xff0c;结果发现光是往SD卡写数据就吃掉了70%的CPU资源。…...

K8s压力测试实战:从HPA动态扩缩容到资源优化

1. 为什么需要K8s压力测试&#xff1f; 当你把业务迁移到Kubernetes集群后&#xff0c;最怕遇到什么情况&#xff1f;我猜一定是半夜被报警叫醒&#xff0c;发现服务因为流量激增而崩溃。去年我们团队就经历过一次&#xff0c;促销活动带来的流量是平时的20倍&#xff0c;HPA&…...

拆解智能车‘心脏’:深度剖析DRV8701E+H桥如何实现电机的精准控制与高效保护

智能车动力心脏解剖&#xff1a;DRV8701E与H桥协同设计中的精密控制艺术 当智能车在赛道上以毫米级精度漂移过弯时&#xff0c;背后是电机驱动系统每秒数千次的电流调节。这场精密舞蹈的核心指挥者&#xff0c;正是DRV8701E这颗高度集成的H桥栅极驱动器。不同于普通驱动芯片的粗…...

MinGW-w64跨平台编译架构设计:实现高性能Windows原生应用开发的最佳实践

MinGW-w64跨平台编译架构设计&#xff1a;实现高性能Windows原生应用开发的最佳实践 【免费下载链接】mingw-w64 (Unofficial) Mirror of mingw-w64-code 项目地址: https://gitcode.com/gh_mirrors/mi/mingw-w64 MinGW-w64是一个开源项目&#xff0c;提供了一套完整的G…...

用QT给MFRC522做个管理工具:从读卡号到读写扇区的完整桌面应用开发实录

基于QT的MFRC522桌面管理工具开发实战&#xff1a;从硬件驱动到批量卡操作 在物联网和智能硬件快速发展的今天&#xff0c;非接触式IC卡技术已经渗透到门禁、支付、身份识别等众多领域。作为开发者&#xff0c;我们经常需要与MFRC522这类射频识别模块打交道&#xff0c;但市面上…...

终极冒险岛游戏编辑器:Harepacker-resurrected新手完全指南

终极冒险岛游戏编辑器&#xff1a;Harepacker-resurrected新手完全指南 【免费下载链接】Harepacker-resurrected All in one .wz file/map editor for MapleStory game files 项目地址: https://gitcode.com/gh_mirrors/ha/Harepacker-resurrected 你是否曾梦想过打造属…...

RK3588设备树移植实战:从零到一构建自定义板级支持包

1. RK3588设备树移植入门指南 如果你正在为基于RK3588芯片的自研硬件平台构建板级支持包&#xff08;BSP&#xff09;&#xff0c;设备树移植是绕不开的关键环节。设备树&#xff08;Device Tree&#xff09;就像硬件的"身份证"&#xff0c;它用文本格式描述硬件配置…...