Swift显式标注协议类型关键词any
Swift显式标注协议类型关键词any

Swift显式标注协议类型关键词any

在 Swift 中,any 是一个 关键字,用于显式地标注 协议类型。它是在 Swift 5.7 中引入的,目的是让代码更清晰并减少对协议类型(existential types)的混淆。

any 的核心作用是区分以下两种情况:

1、协议类型作为值(any Protocol)。

2、协议类型作为泛型约束(不需要 any 关键字)。

为什么需要 any?

在引入 any 之前,直接写协议类型(如 Decoder、Hashable)实际上表示了一个 existential type(协议存在类型),但这一点并不明显,容易导致代码语义模糊。

例如

let decoder: Decoder:这指的是一个协议值。

let decoder: some Decoder:这是一个符合 Decoder 协议的具体类型(泛型)。

func process<T: Decoder>(_ decoder: T):这是一个泛型函数,使用泛型约束。

Swift 团队引入 any 来明确区分协议类型和泛型约束

如果你明确想使用一个 协议类型的值,需要加上 any,如 any Decoder。

如果不加 any,Swift 会假定你想用泛型约束(或具体类型)。

any 的用途

1、显式声明协议类型

使用 any,表示这是一个协议类型的值,而不是某个具体的实现类型。

示例

let value: any Hashable // 一个符合 Hashable 协议的值,不限具体类型

在这里,value 可以是任何符合 Hashable 协议的类型(如 Int、String 等)。

2、与泛型约束对比

使用泛型约束(如 T: Protocol)时,编译器会优化为特定的具体类型。

而 any 是运行时存在的协议值,性能略低。

示例对比

func printValue<T: Hashable>(_ value: T) {
    print(value)
}

泛型函数 printValue 是在编译时决定 T 的具体类型(例如 Int 或 String)。

func printValue(_ value: any Hashable) {
    print(value)
}

此函数接受 任何类型的值,只要它符合 Hashable 协议。

3、在函数参数中使用

如果一个参数需要接受协议类型作为值,可以显式地使用 any:

func performAction(with value: any Decodable) {
    // 处理符合 Decodable 的值
}

4、在属性或变量中使用

当属性需要存储一个协议类型的值时,any 可以明确类型语义:

var items: [any Hashable] = [1, "Hello", 3.14]

在这个例子中,items 数组可以存储任意符合 Hashable 的值。

any 的特点

1、性能区别

使用 any 时,Swift 会将协议类型的值存储在一个 existential container 中,包含类型信息和方法表。这种方式会有一定的性能开销。

使用泛型时,编译器会在编译期优化为具体类型,因此性能更高。

2、语法清晰

使用 any 明确指出一个值是协议类型,而不是泛型。

3、适用场景

当你需要运行时存储、传递协议类型的值时(例如多态场景),使用 any 是合适的。

如果性能敏感,且类型已知,建议使用泛型。

示例代码

以下代码演示了如何使用 any 和泛型:

protocol Shape {
    func draw()
}

struct Circle: Shape {
    func draw() {
        print("Drawing a circle")
    }
}

struct Square: Shape {
    func draw() {
        print("Drawing a square")
    }
}

// 使用 `any Shape` (协议类型)
let shapes: [any Shape] = [Circle(), Square()]
for shape in shapes {
    shape.draw()
}

// 使用泛型 (编译时确定类型)
func drawShape<T: Shape>(_ shape: T) {
    shape.draw()
}

drawShape(Circle())
drawShape(Square())

总结

any 的核心作用:让协议类型的语义更加清晰。

何时使用 any

当你需要处理符合协议的值,而不是具体类型。

当你需要多态或运行时存储协议类型的值

何时不使用 any

当性能敏感,或者类型在编译时已知时,使用泛型或具体类型更高效。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注