Swift 开发教程系列 - 第12章:协议与协议扩展

协议(Protocol)是 Swift 的一种重要特性,它定义了实现特定功能的方法、属性或其他要求。通过协议,可以将行为定义从具体实现中分离,使代码更具可读性和扩展性。Swift 的协议支持协议扩展,这一特性允许我们为协议定义默认实现,使得协议不仅仅是一个要求的集合,还可以具备部分功能。

12.1 什么是协议

协议定义了一组用于实现特定功能的方法或属性。任何符合该协议的类型都必须实现这些方法和属性,确保符合协议的类型拥有相似的功能和行为。

协议示例

protocol Drivable {var speed: Double { get set }func drive()
}class Car: Drivable {var speed: Double = 0.0func drive() {print("Driving at \(speed) km/h")}
}let myCar = Car()
myCar.speed = 80.0
myCar.drive()  // 输出:"Driving at 80.0 km/h"

在上例中,Drivable 协议要求任何符合该协议的类型都必须实现 speed 属性和 drive() 方法。Car 类遵循 Drivable 协议,并提供了具体的实现。

12.2 协议中的属性和方法

协议不仅可以定义方法,还可以定义属性和下标(subscript)。协议中的属性可以是只读的,也可以是可读写的。

  1. 只读属性:使用 { get } 声明只读属性,符合该协议的类型必须实现此属性。
  2. 可读写属性:使用 { get set } 声明可读写属性,符合该协议的类型必须支持读取和写入。

示例代码

protocol Identifiable {var id: String { get }
}struct User: Identifiable {var id: String
}let user = User(id: "12345")
print("User ID: \(user.id)")  // 输出:"User ID: 12345"

在上例中,Identifiable 协议定义了一个只读属性 id,符合协议的类型 User 实现了此属性。

12.3 协议的继承

Swift 的协议支持继承,可以从一个协议继承多个协议,并添加自己的要求。

示例代码

protocol Vehicle {var maxSpeed: Double { get }
}protocol Drivable: Vehicle {func drive()
}class Bicycle: Drivable {var maxSpeed: Double = 25.0func drive() {print("Cycling at a safe speed.")}
}let bike = Bicycle()
bike.drive()  // 输出:"Cycling at a safe speed."

在上例中,Drivable 协议继承自 Vehicle 协议,这意味着任何符合 Drivable 的类型必须同时满足 Vehicle 的要求。

12.4 协议组合

Swift 支持将多个协议组合在一起,定义一个新类型,该类型必须同时符合多个协议的要求。

示例代码

protocol Named {var name: String { get }
}protocol Aged {var age: Int { get }
}struct Person: Named, Aged {var name: Stringvar age: Int
}func printInfo(of person: Named & Aged) {print("\(person.name) is \(person.age) years old")
}let alice = Person(name: "Alice", age: 30)
printInfo(of: alice)  // 输出:"Alice is 30 years old"

在上例中,函数 printInfo 的参数类型 Named & Aged 表示参数必须同时符合 Named 和 Aged 协议。

12.5 协议扩展

协议扩展允许你为协议提供默认实现,使得符合该协议的类型可以直接使用这些实现,而无需自行实现。这样可以避免代码重复,并使协议的行为更为一致。

示例代码

protocol Greetable {var name: String { get }func greet()
}extension Greetable {func greet() {print("Hello, \(name)!")}
}struct Friend: Greetable {var name: String
}let friend = Friend(name: "John")
friend.greet()  // 输出:"Hello, John!"

在上例中,Greetable 协议的扩展提供了 greet() 方法的默认实现,因此符合协议的 Friend 结构体可以直接调用 greet() 方法,而无需自己实现。

12.6 协议的应用场景

  1. 接口设计:通过协议定义模块的公共接口,使代码更具模块化和可读性。
  2. 依赖注入:使用协议替代具体类型,可以实现更灵活的依赖注入。
  3. 委托模式:在委托模式中,协议用于定义委托对象的方法和属性,使不同类型的对象可以通过协议进行交互。
  4. 类型约束:在泛型编程中,使用协议作为类型约束,确保泛型类型符合特定要求。

委托模式示例

protocol DataSource {func fetchData() -> [String]
}class TableView {var dataSource: DataSource?func reloadData() {if let data = dataSource?.fetchData() {print("Data: \(data)")}}
}class DataProvider: DataSource {func fetchData() -> [String] {return ["Item 1", "Item 2", "Item 3"]}
}let tableView = TableView()
tableView.dataSource = DataProvider()
tableView.reloadData()  // 输出:"Data: ["Item 1", "Item 2", "Item 3"]"

在上例中,DataSource 协议定义了 fetchData() 方法,使 TableView 类不需要知道具体的数据来源,而是通过协议获取数据。

12.7 协议的优点

  1. 灵活性:协议可以帮助实现松耦合的设计,使代码更具模块化和灵活性。
  2. 可扩展性:协议扩展使得协议不只是一个要求的集合,还可以包含默认实现,方便扩展协议的功能。
  3. 代码复用:通过协议和协议扩展,可以避免重复代码,提高代码的复用性。
  4. 类型安全:Swift 的类型检查确保协议实现的安全性,避免了运行时错误。

通过本章的学习,你将会发现协议在 Swift 开发中扮演着至关重要的角色,使代码更加灵活、可扩展,并且容易维护。下一章将探讨 Swift 的错误处理机制(Error Handling),帮助你编写更加健壮和稳定的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/468083.html

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

相关文章

HTB:Perfection[WriteUP]

目录 连接至HTB服务器并启动靶机 1.What version of OpenSSH is running? 使用nmap对靶机TCP端口进行开放扫描 2.What programming language is the web application written in? 使用浏览器访问靶机80端口页面,并通过Wappalyzer查看页面脚本语言 3.Which e…

SDL打开YUV视频

文章目录 问题1:如何控制帧率?问题2:如何触发退出事件?问题3:如何实时调整视频窗口的大小问题4:YUV如何一次读取一帧的数据? 问题1:如何控制帧率? 单独用一个子线程给主线…

Android V 挂起线程超时导致system_server挂掉

问题背景 最近Android v的平台频繁爆monkey异常停止的问题,分析到根因不是频繁dump堆栈导致system_server挂掉就是三方应用进程内部死锁导致anr,然后system_server挂起线程超时,system_server就崩了。 解决方案 先来看看anr导致死锁的场景如何分析 从log来看确认为syste…

下载mysql的jar,添加至jmeter中,编写jdbc协议脚本1106

下载jar包: 步骤1:进入maven仓库官网https://mvnrepository.com/ 步骤2:搜索实际的数据库 步骤3:点击 Mysql connnector/J 步骤5、查看数据库的版本号,选择具体版本,我的是mysql 8.0.16,下图,…

【分布式】分布式锁设计与Redisson源码解析

分布式锁 分布式锁是一种在分布式计算环境中用于控制多个节点(或多个进程)对共享资源的访问的机制。在分布式系统中,多个节点可能需要协调对共享资源的访问,以防止数据的不一致性或冲突。分布式锁允许多个节点在竞争访问共享资源…

CAD 图元 动一下消失

Z.ed.DrawVector(Point3d.Origin, new Point3d(100, 100, 0), 1, true);

【计网】实现reactor反应堆模型 --- 处理数据发回问题 ,异常处理问题

没有一颗星, 会因为追求梦想而受伤, 当你真心渴望某样东西时, 整个宇宙都会来帮忙。 --- 保罗・戈埃罗 《牧羊少年奇幻之旅》--- 实现Reactor反应堆模型 1 数据处理2 数据发回问题3 异常处理问题4 运行效果 1 数据处理 在上一篇文章中我…

Science Robotics 综述揭示演化研究新范式,从机器人复活远古生物!

在地球46亿年的漫长历史长河中,生命的演化过程充满着未解之谜。如何从零散的化石证据中还原古生物的真实面貌?如何理解关键演化节点的具体过程?10月23日,Science Robotics发表重磅综述,首次系统性提出"古生物启发…

string接口的深度理解(内附思维导图)

1. 为什么学习string类? C语言中的字符串 C语言中,字符串是以\0结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列 的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想&#xff0…

python可视化将多张图整合到一起(画布)

这周有点事忙着,没时间重温刚结束的Mathurcup数学建模,这两天也是再看了下,论文还是赶紧挺烂的,但比国赛又有进步(说起国赛又不得不抱怨了,基本其余省份都发了,但江西......哎)。哎&…

jsp+sevlet+mysql实现用户登陆和增删改查功能

jspsevletmysql实现用户登陆和增删改查功能 一、系统介绍二、功能展示1.用户登陆2.用户列表3.查询用户信息4.添加用户信息5.修改用户信息6.删除用户信息 四、其它1.其他系统实现 一、系统介绍 系统主要功能: 用户登陆、添加用户、查询用户、修改用户、删除用户 二…

Python小白学习教程从入门到入坑------第二十九课 访问模式文件定位操作(语法进阶)

一、访问模式 模式可做操作若文件不存在是否覆盖r只能读报错-r可读可写报错是w只能写创建是w可读可写创建是a只能写创建否,追加写a可读可写创建否,追加写 1.1 r r:只读模式(默认模式),文件必须存在,不存在就会报错…

TIOBE 编程指数 11 月排行榜公布 VB.Net第九

IT之家 11 月 9 日消息,TIOBE 编程社区指数是一个衡量编程语言受欢迎程度的指标,评判的依据来自世界范围内的工程师、课程、供应商及搜索引擎,今天 TIOBE 官网公布了 2024 年 11 月的编程语言排行榜,IT之家整理如下: P…

聚合联盟的优势

聚合广告联盟对比其他平台优势: 数据透明,自己去平台查看不存在扣量问题。对OVHM做策略优化,帮助开发者做多重点击和下载,使开发者利益最大化。为开发者提供app各大市场上架,隐私协议等指导。 最大的优势就是数据公开…

FakeLocation 版本问题

前言:最新版的FakeLocation 1.3.5 BETA版本在appconfigs.xml文件种添加了绝大多数的应用,导致会返回真实的物理位置,在1.3.2.2都没有这个问题,但是旧版是会被强制更新,不然无法使用. 版本问题/注入/代理 方法 需要使用FakeLocation有二种办法…

算法(第一周)

一周周五,总结一下本周的算法学习,从本周开始重新学习许久未见的算法,当然不同于大一时使用的 C 语言以及做过的简单题,现在是每天一题 C 和 JavaScript(还在学,目前只写了一题) 题单是代码随想…

大语言模型LLMs在医学领域的最新进展总结

我是娜姐 迪娜学姐 ,一个SCI医学期刊编辑,探索用AI工具提效论文写作和发表。 相比其他学科,医学AI,是发表学术成果最多的领域。 医学数据的多样性和复杂性(包括文本、图像、基因组数据等),使得…

服务器被病毒入侵如何彻底清除?

当服务器遭遇病毒入侵时,彻底清除病毒是确保系统安全和数据完整性的关键步骤。这一过程不仅需要技术上的精准操作,还需要严密的计划、合理的资源调配以及后续的防范措施。以下是一篇关于如何在服务器被病毒入侵时彻底清除病毒的详细指南。 一、初步响应与…

Javascript中如何实现函数缓存?函数缓存有哪些应用场景?

#一、是什么 函数缓存,就是将函数运算过的结果进行缓存 本质上就是用空间(缓存存储)换时间(计算过程) 常用于缓存数据计算结果和缓存对象 解释 const add (a,b) > ab; const calc memoize(add); // 函数缓存…

基于LLaMA-Factory微调Llama3

本文简要介绍下基于LLaMA-Factory的llama3 8B模型的微调过程 环境配置 # 1. 安装py3.10虚拟环境 conda create -n py3.10-torch2.2 python3.10 source activate conda activate py3.10-torch2.2# 2. 安装cuda12.2 gpu版torch2.2 conda install pytorch2.2.2 torchvision0.17.…