Swift 5.9 新特性:值和类型参数包

前言

在 Swift5.9 的版本中,经过 Apple 进行一系列的改动,可以允许开发者使用可变泛型参数。

上述改动解决了 Swift 中的一个很重要问题,就是泛型函数需要特定数量的类型参数。虽然这些函数仍然可以接受可变参数,但它们最终仍然必须使用相同的类型。

比如下面的例子,假设我们三个不同的结构体用来代表程序员不同的角色:

arduino 复制代码
struct FrontEndDev {
    var name: String
}

struct BackEndDev {
    var name: String
}

struct FullStackDev {
    var name: String
}

当然,在实际需求中这些结构体会有更多的属性用来实现需求,但此处仅是举例,所以只给结构体一个 name 的属性。

接着我们为每个结构体创建实例:

ini 复制代码
let johnny = FrontEndDev(name: "Johnny Appleseed")
let jess = FrontEndDev(name: "Jessica Appleseed")
let kate = BackEndDev(name: "Kate Bell")
let kevin = BackEndDev(name: "Kevin Bell")

let derek = FullStackDev(name: "Derek Derekson")

然后,当涉及到实际工作时,我们可以使用一个简单的函数将开发人员匹配在一起,如下所示:

swift 复制代码
func pairUp1<T, U>(firstPeople: T..., secondPeople: U...) -> ([(T, U)]) {
    assert(firstPeople.count == secondPeople.count, "You must provide equal numbers of people to pair.")
    var result = [(T, U)]()

    for i in 0..<firstPeople.count {
        result.append((firstPeople[i], secondPeople[i]))
    }

    return result
}

它使用两个可变参数来接收一组第一个人和一组第二个人,然后将它们作为数组返回。我们现在可以使用它来创建一个组程序员,改组需要处理某些前端和后端的工作。

ini 复制代码
let result1 = pairUp1(firstPeople: johnny, jess, secondPeople: kate, kevin)

到目前为止,都是按照 Swift 5.9 之前的版本去写的代码。但有趣的是: Derek 是一名全栈开发人员,因此既可以担任后端开发人员,也可以担任前端开发人员。然而,如果我们尝试使用johnny, derek作为第一个参数,那么 Swift 编译器将会报错。因为它需要第一个人和第二个人的类型是相同的。

我们可以使用 any 关键字来抹除所有的类型信息,从而解决这个问题。但这样就失去了很多可以利用的 Swift 特性,我们可以用参数包来更优雅的解决这个问题。

参数包

乍一开始看到这个语法可能会有点懵,下面先写出完整代码,后面再一点点分解它:

sql 复制代码
func pairUp2<each T, each U>(firstPeople: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second: each U)) {
    return (repeat (each firstPeople, each secondPeople))
}

让我们分解成四部分来理解它:

  • <each T, each U> 创建了两个类型参数包, TU
  • repeat each T 是一个包扩展,它将参数包扩展为实际值 - 它相当于 T...,但避免了与 ... 用作运算符造成混淆
  • 返回类型意味着我们要发回配对程序员的元组,TU 各一个
  • return 关键字的作用:它使用包扩展表达式从 T 中获取一个值,从 U 中获取一个值,然后将它们组合在一起形成返回值

需要注意的是,返回类型会自动确保我们的 TU 类型具有相同的形状------它们内部具有相同数量的元素。因此,如果我们试图传入两组不同大小的数据,Swift 会编译报错,而不是像在第一个函数中那样使用assert()

下面是新函数的调用示例:

ini 复制代码
let result2 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, kevin)
相关推荐
良技漫谈2 天前
Rust移动开发:Rust在iOS端集成使用介绍
后端·程序人生·ios·rust·objective-c·swift
KeithTsui2 天前
ZFC in LEAN 之 前集的等价关系(Equivalence on Pre-set)详解
开发语言·其他·算法·binder·swift
袁代码2 天前
Swift 开发教程系列 - 第4章:函数与闭包
ios·swift·ios开发
安泽13143 天前
高德地图美食
开发语言·swift·美食
袁代码4 天前
Swift 开发教程系列 - 第2章:Swift 基础语法
swift·ios开发·基础教程
袁代码4 天前
Swift 开发教程系列 - 第1章:Swift 简介与开发环境配置
swift·ios开发·基础教程
孚亭4 天前
一些swift问题
swift
莫问alicia4 天前
echarts 实现3D饼状图 加 label标签显示
前端·3d·echarts·swift
uiop_uiop_uiop7 天前
iOS Swift5算法恢复——HMAC
ios·iphone·swift
東三城8 天前
【ios】---SwiftUI开发从入门到放弃
ios·swiftui·swift·1024程序员节