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

Swift 中 associatedtype 的用法详解

目录

前言

1.什么是associatedtype

2.associatedtype 的作用

1.让协议支持泛型

2.让协议支持不同的数据类型

3.结合 where 关键字限制类型

4.什么时候使用 associatedtype

5.总结


前言

        在 Swift 语言中,泛型(Generics)是一个非常强大的特性,它允许我们编写灵活且可复用的代码。而当我们在 协议(Protocol) 中需要使用泛型时,associatedtype 就派上了用场。

        本文将详细介绍 associatedtype 的作用、使用场景,并通过代码示例帮助大家更好地理解它的使用方式。

1.什么是associatedtype

        在 Swift 的协议中,我们无法直接使用泛型 <T>,但可以使用 associatedtype 关键字来声明一个占位类型,让协议在不确定具体类型的情况下仍然能够正常使用。

        associiatedtype的语法如下:

protocol SomeProtocol {associatedtype SomeTypefunc doSomething(with value: SomeType)
}
  1. associatedtype SomeType:声明一个占位类型 SomeType,但不指定具体类型。
  2. func doSomething(with value: SomeType):SomeType 由实现该协议的类型决定。

        这样,任何遵循 SomeProtocol 的类型都可以自定义 SomeType 为任何符合需求的类型,从而提高协议的通用性。

2.associatedtype 的作用

1.让协议支持泛型

        假设我们想设计一个容器(Container)协议,让它能够存储不同类型的元素,如果不用 associatedtype,我们可能会写成:

protocol Container {func append(_ item: Int)func getItem(at index: Int) -> Int
}

        这个协议只能存储 Int 类型的元素,缺乏灵活性。

        而使用 associatedtype,可以让它支持任意类型:

protocol Container {associatedtype Itemfunc append(_ item: Item)func getItem(at index: Int) -> Item
}

        现在,我们可以创建不同类型的容器:

struct IntContainer: Container {typealias Item = Int  // 指定 Item 为 Int 类型private var items: [Int] = []func append(_ item: Int) {items.append(item)}func getItem(at index: Int) -> Int {return items[index]}
}struct StringContainer: Container {typealias Item = String  // 指定 Item 为 String 类型private var items: [String] = []func append(_ item: String) {items.append(item)}func getItem(at index: Int) -> String {return items[index]}
}

        这样 IntContainer 和 StringContainer 都遵循 Container 协议,但它们的 Item 类型不同,提高了代码的通用性。

2.让协议支持不同的数据类型

        假设我们要设计一个**栈(Stack)**数据结构,它应该支持不同的数据类型,比如 Int、String 等:

protocol StackProtocol {associatedtype Elementmutating func push(_ item: Element)mutating func pop() -> Element?
}

        不同的数据类型可以实现这个协议:

struct IntStack: StackProtocol {typealias Element = Intprivate var stack: [Int] = []mutating func push(_ item: Int) {stack.append(item)}mutating func pop() -> Int? {return stack.popLast()}
}struct StringStack: StackProtocol {typealias Element = Stringprivate var stack: [String] = []mutating func push(_ item: String) {stack.append(item)}mutating func pop() -> String? {return stack.popLast()}
}

        IntStack 和 StringStack 都遵循 StackProtocol,但 Element 类型可以不同!

3.结合 where 关键字限制类型

        有时候,我们希望 associatedtype 只能是某种类型的子类或实现了某个协议。可以使用 where 关键字进行类型约束:

protocol Summable {associatedtype Number: Numeric  // 限定 Number 必须是 Numeric 协议的子类型func sum(a: Number, b: Number) -> Number
}

        实现 Summable 协议:

struct IntegerAdder: Summable {func sum(a: Int, b: Int) -> Int {return a + b}
}struct DoubleAdder: Summable {func sum(a: Double, b: Double) -> Double {return a + b}
}

        这里 Number 只能是 Int、Double 之类的 Numeric 类型,保证了类型安全。

3.associatedtype 与泛型的区别

比较项

associatedtype(协议中的泛型)

普通泛型 <T>

适用范围

只能用于 协议

可用于 类、结构体、函数

作用

让协议支持不确定的类型,由实现者决定具体类型

让类型/函数支持泛型

例子

protocol Container { associatedtype Item }

struct Stack<T> {}

限制

只能用于协议,不能直接实例化

适用于所有类型

4.什么时候使用 associatedtype

       当你需要创建一个通用的协议,但不想限定某个具体类型时。

        当不同的实现类需要指定不同的数据类型时。

        当你希望协议中的某些类型参数具备类型约束时(如 where 关键字)。

5.总结

        associatedtype允许协议拥有不确定的类型,由实现者决定具体类型。

        让协议支持泛型,使其更加通用,适用于不同的数据类型。

        可以通过where限制类型范围,提高安全性。

        适用于 协议,而泛型 <T> 适用于类、结构体和函数。

        一句话总结:associatedtype 就是协议的泛型,让协议更加灵活和可扩展!

相关文章:

Swift 中 associatedtype 的用法详解

目录 前言 1.什么是associatedtype 2.associatedtype 的作用 1.让协议支持泛型 2.让协议支持不同的数据类型 3.结合 where 关键字限制类型 4.什么时候使用 associatedtype 5.总结 前言 在 Swift 语言中&#xff0c;泛型&#xff08;Generics&#xff09;是一个非常强大…...

java泛型通配符?及上下界(extends,super)保证安全性、灵活性、可读性

在 Java 中&#xff0c;泛型通配符&#xff08;?&#xff09;用于表示未知类型&#xff0c;通常用于增强泛型的灵活性。通配符可以与上下限结合使用&#xff0c;以限制泛型的范围。以下是通配符及上下限的使用示例&#xff1a; 1. 无界通配符 (?) 无界通配符表示可以接受任意…...

HarmonyOS NEXT - 网络请求问题(http)

HTTP&#xff08;HyperText Transfer Protocal&#xff0c;超文本传输协议&#xff09;是一种用于传输超媒体文档&#xff08;如HTML&#xff09;的应用层协议&#xff0c;它是客户端和服务器之间通信的基础&#xff1b;无论是获取数据、提交表单、上传文件&#xff0c;HTTP都扮…...

告别旧版本,功能全面升级!

小伙伴们&#xff0c;今天来给大家唠唠一款超经典的软件——格式工厂&#xff01;相信很多人都不陌生吧&#xff1f;它可是早期超多人用的视频格式转换工具呢&#xff01;但随着软件行业的发展&#xff0c;它慢慢被其他工具代替了&#xff0c;像万兴、小丸、AME这些新宠儿一出现…...

WSL2 Ubuntu安装GCC不同版本

WSL2 Ubuntu安装GCC不同版本 介绍安装gcc 7.1方法 1&#xff1a;通过源码编译安装 GCC 7.1步骤 1&#xff1a;安装编译依赖步骤 2&#xff1a;下载 GCC 7.1 源码步骤 3&#xff1a;配置和编译步骤 4&#xff1a;配置环境变量步骤 5&#xff1a;验证安装 方法 2&#xff1a;通过…...

双目视觉小记

双目视觉及其数学原理 1. 双目视觉概述 双目视觉&#xff08;Stereo Vision&#xff09;是一种模仿人眼视觉系统的计算机视觉技术&#xff0c;利用两台摄像机从不同角度拍摄同一场景&#xff0c;通过图像处理和三维重建来获取场景的深度信息。双目视觉广泛应用于机器人、自动…...

Obsidian Copilot:打造你的专属 AI 笔记助手

Obsidian Copilot作为一款非常受欢迎的Obsidian插件&#xff0c;不仅极大地提升了用户的笔记管理和信息检索效率&#xff0c;还通过其多样化的AI功能为用户带来了前所未有的便捷体验。本文将详细介绍Obsidian Copilot的核心特点、使用方法及个人体验分享。 核心特点 Obsidian…...

VPC4-通达oa-docker逃逸-shiro反序列化-hash传递-CrackMapExec喷射-历史ptt攻击-进程注入

由于本人是菜鸡&#xff0c;不会免杀&#xff0c;所有免杀的部分就直接跳过了 &#xff08;hhh) 靶场地址&#xff1a; 链接: https://pan.baidu.com/s/1Fh1Zg79n1yjCPe6rrQ2apA 提取码: qiag 第一台ubuntu(docker逃逸&#xff0c;shiro反序列化&#xff09; fscan扫到一…...

稳定运行的以Oracle数据库为数据源和目标的ETL性能变差时提高性能方法和步骤

要提高以 Oracle 为数据源和目标的ETL性能&#xff0c;需要综合考虑数据库性能优化、ETL工具配置、查询优化、并行处理和资源管理等多个方面。优化过程中要根据具体的ETL场景和工具来选择适合的方案&#xff0c;同时建议进行逐步调优&#xff0c;测试不同方案的效果&#xff0c…...

C++类与对象——拷贝构造与运算符重载

拷贝构造函数和赋值运算符重载就是C类默认六个函数之二。 拷贝构造函数&#xff1a; 如果⼀个构造函数的第⼀个参数是自身类类型的引用&#xff0c;且任何额外的参数都有默认值&#xff0c;则此构造函数 也叫做拷贝构造函数&#xff0c;也就是说拷贝构造是⼀个特殊的构造函数…...

疗养院管理系统设计与实现(代码+数据库+LW)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装疗养院管理系统软件来发挥其高效地信息处理的作用&#xf…...

2024年12月CCF-GESP编程能力等级认证C++编程四级真题解析

四级真题的难度: 一、总体难度评价 CCF-GESP编程能力等级认证C++四级真题的难度通常被认为相对较高。它不仅要求考生具备扎实的C++编程基础,还需要考生掌握一定的算法和数据结构知识,以及良好的问题解决能力。 二、具体难度分析 ‌理论知识考察‌: 单选题和判断题中,会涉…...

MySQL开发陷阱与最佳实践:第1章:MySQL开发基础概述-1.1 MySQL简介与应用场景

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 MySQL开发陷阱与最佳实践&#xff1a;第1章&#xff1a;MySQL开发基础概述-1.1 MySQL简介与应用场景1.1.1 MySQL的发展历程与市场地位1.1.2 MySQL的核心特性与技术优势1.1.2…...

使用GitHub Actions实现Git推送自动部署到服务器

将网站一键部署到服务器的方案很多&#xff0c;比如纯Shell脚本结合SSH、Jenkins等工具。本文将介绍如何利用GitHub Actions这一免费且轻量的CI/CD工具&#xff0c;实现代码推送后自动部署到云服务器。 之前一直在使用github的工作流&#xff0c;确实是一个比较好用的工具。 我…...

PyTorch 系列教程:探索自然语言处理应用

本文旨在介绍如何使用PyTorch进行自然语言处理&#xff08;NLP&#xff09;的基础知识&#xff0c;包括必要的库、概念以及实际代码示例。通过阅读本文&#xff0c;您将能够开始您的NLP之旅。 1. 理解PyTorch PyTorch是一个开源的机器学习库&#xff0c;基于Torch库&#xff0…...

3.14-1列表

列表 一.列表的介绍和定义 1 .列表 类型: <class list> 2.符号:[] 3.定义列表: 方式1:[] 通过[] 来定义 list[1,2,3,4,6] print(type(list)) #<class list> 方式2: 通过list 转换 str2"12345" print(type(str2)) #<class str> list2lis…...

什么是强哈希算法pbkdf2(Password-Based Key Derivation Function)

文章目录 什么是pbkdf2使用场景 在线工具 什么是pbkdf2 维基百科&#xff1a;https://zh.wikipedia.org/zh-cn/PBKDF2 PBKDF2&#xff08;Password-Based Key Derivation Function 2&#xff09;是一种基于密码的密钥派生函数。它的主要作用是从密码和盐&#xff08;salt&…...

<meta content=“no-siteapp“ data-n-head=“ssr“ http-equiv=“Cache-Control“/>什么作用?

<meta content"no-siteapp" data-n-head"ssr" http-equiv"Cache-Control"/> 这个标签的作用是禁止某些浏览器或工具将网页转换为“应用”形式&#xff0c;尤其是针对一些特定的浏览器&#xff08;如早期的 UC 浏览器&#xff09;或移动端工…...

pyroSAR:开源的SAR数据处理与分析工具

今天为大家介绍的软件是pyroSAR&#xff1a;一款开源的SAR数据处理与分析工具。下面&#xff0c;我们将从软件的主要功能、支持的系统、软件官网等方面对其进行简单的介绍。 pyroSAR官网网址为&#xff1a;https://pyrosar.readthedocs.io/en/latest/。 pyroSAR是一个开源Pytho…...

Visual Studio里的调试(debugging)功能介绍

参考 1- Introduction to Debugging | Basic Visual Studio Debugging&#xff08;这是一位印度博主视频&#xff0c;我下面做到笔记也主要参考她的视频&#xff0c;但不得不说口音太重了&#xff0c;一股咖喱味&#xff09; 目录 个人对调试浅显的认识和对调试的介绍逐行调…...

图论part4|827. 最大人工岛、127. 单词接龙、463. 岛屿的周长

827. 最大人工岛 &#x1f517;&#xff1a;827. 最大人工岛 - 力扣&#xff08;LeetCode&#xff09;827. 最大人工岛 - 给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。返回执行此操作后&#xff0c;grid 中最大的岛屿面积是多少&#xff1f;岛屿 由一…...

Java高级-05.反射的作用、应用场景

一.反射的作用 二.案例 Student.class package com.njau.d2_reflect;public class Student {private String name;private int age;private char sex;private double height;private String hobby;public Student(String name, int age, char sex, double height, String …...

CSS中粘性定位

1.如何设置为粘性定位? 给元素设置posttion:sticky 即可实现粘性定位. 可以使用left, right ,top, bottom 四个属性调整位置,不过最常用的是top 值. 2.粘性定位的参考点在哪里? 离他最近的一个拥有"滚动机制"的祖先元素,即便这个祖先不是最近的真实可滚动祖先. 3.粘…...

CockroachDB MCP -cursor适用

CockroachDB MCP 服务器 GitHub仓库置顶 这是一个用于 Cursor 的 CockroachDB MCP 服务器&#xff0c;基于 Model Context Protocol (MCP) 规范实现&#xff0c;可以让你在 Cursor 中直接与 CockroachDB 数据库交互。 功能 连接到 CockroachDB 数据库获取数据库中的所有表获…...

cherry-studio - 多模型支持的跨平台 AI 桌面助手

GitHub&#xff1a;https://github.com/CherryHQ/cherry-studio 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI 一款支持多种大语言模型服务的跨平台桌面客户端&#xff0c;兼容 Windows、Linux 和 macOS 系统。它支持主流云端模型&am…...

docker composeyaml文件,什么是swap-space,内存不足硬盘来凑,--ipc=host,yaml文件、环境变量、容器报警健康检查

--swap-space 参数明确针对的是系统内存&#xff08;RAM&#xff09;&#xff0c;与显存&#xff08;GPU Memory&#xff09;无关。以下是关键区分&#xff1a; 内存&#xff08;RAM&#xff09; vs 显存&#xff08;GPU Memory&#xff09; 类型内存&#xff08;RAM&#xff…...

Uniapp 开发 App 端上架用户隐私协议实现指南

文章目录 引言一、为什么需要用户隐私协议&#xff1f;二、Uniapp 中实现用户隐私协议的步骤2.1 编写隐私协议内容2.2 在 Uniapp 中集成隐私协议2.3 DCloud数据采集说明2.4 配置方式3.1 Apple App Store3.2 Google Play Store 四、常见问题与解决方案4.1 隐私协议内容不完整4.2…...

Gradio ,一个实用的大模型界面

Gradio是HuggingFace的开源项目&#xff0c;GitHub 28k star。能够方便地构建AI应用的网页界面。 最大的优点是简便。对于不熟悉前端的程序员&#xff0c;能够迅速地构建基于web的AI应用。 Hello World import gradio as gr ​ def print_text(text):return "Hello Wor…...

LeetCode 环形链表II:为什么双指针第二次会在环的入口相遇?

快慢指针 为什么相遇后让快指针回到起点&#xff0c;再让快指针和慢指针都一步一步地走&#xff0c;它们就会在环的入口相遇&#xff1f; 复杂度 时间复杂度: O(n) 空间复杂度: O(1) public ListNode detectCycle(ListNode head) {ListNode slow head, fast head;ListNode …...

如何处理PHP中的编码问题

如何处理PHP中的编码问题 在PHP开发过程中&#xff0c;编码问题是一个常见且棘手的问题。无论是处理用户输入、数据库交互&#xff0c;还是与外部API通信&#xff0c;编码问题都可能导致数据乱码、解析错误甚至安全漏洞。本文将深入探讨PHP中的编码问题&#xff0c;并提供一些…...