Swift 中 associatedtype 的用法详解

news2025/3/16 6:30:21

目录

前言

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 SomeType
    func 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 Item
    func 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 Element
    mutating func push(_ item: Element)
    mutating func pop() -> Element?
}

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

struct IntStack: StackProtocol {
    typealias Element = Int
    private var stack: [Int] = []

    mutating func push(_ item: Int) {
        stack.append(item)
    }

    mutating func pop() -> Int? {
        return stack.popLast()
    }
}

struct StringStack: StackProtocol {
    typealias Element = String
    private 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 就是协议的泛型,让协议更加灵活和可扩展!

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

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

相关文章

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

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

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

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

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扫到一…

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…

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 …

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

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

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…

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;并提供一些…

【动手学强化学习】part8-PPO(Proximal Policy Optimization)近端策略优化算法

阐述、总结【动手学强化学习】章节内容的学习情况&#xff0c;复现并理解代码。 文章目录 一、算法背景1.1 算法目标1.2 存在问题1.3 解决方法 二、PPO-截断算法2.1 必要说明2.2 伪代码算法流程简述 2.3 算法代码2.4 运行结果2.5 算法流程说明 三、疑问四、总结 一、算法背景 …