Swift:类型别名和在协议中带有值的关联类型有什么区别?

dea*_*.dg 8 type-alias associated-types swift swift-protocols

在 Swift 中,以下代码编译没有问题。

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这些似乎表现得几乎相同。我注意到的唯一区别是对何时可以使用有额外的限制,P1因为它具有关联类型。特别是,let x: P1是一个错误而let x: P2很好。

这两种协议之间的实际区别是什么?它们在编译代码中的处理方式不同吗?最后,使用P1而不是有优势P2吗?

为清楚起见编辑:

我知道关联类型和类型别名之间的工作差异,所以我很惊讶你甚至可以给关联类型一个固定值。这似乎违背了关联类型的全部目的。我想知道是否有任何实用程序可以为关联类型提供固定值,并且我想知道这两个协议在编译后是否不同。

Fog*_*ter 8

在代码中你写是不是一个真正的功能不同,因为你已经设置associatedtypeInt

要从它们中获得更强大的用法,您可以将associatedtype用作伪通用约束。

所以你可以这样写......

protocol P1 {
    associatedtype Item: Equatable
    var itemArray: [Item] { get set }
    mutating func add(item: Item)
}

extension P1 {
    mutating func add(item: Item) {
        itemArray.append(item)
    }
}

struct StructWithStrings: P1 {
    var itemArray: [String]
}

struct StructWithInts: P1 {
    var itemArray: [Int]
}
Run Code Online (Sandbox Code Playgroud)

因为它们都符合 P1 并且它们都将它们的数组类型设置为Equatable类型。编译器可以推断出add(item: Item)函数的正确类型并在编译时提供帮助。

与此相反...typealias只是为了方便起见真正用于更改某些类型的名称。例如,您可能会像……一样使用闭包(Data?, Error?, URLResponse) -> (),多次编写它会很长,但也会失去一些意义。所以你可以这样做...

typealias DownloadResponse = (Data?, Error?, URLResponse) -> ()
Run Code Online (Sandbox Code Playgroud)

并将所有用法替换为DownloadResponse.

associatedtypeSwift 中有很多优秀的资源......

  1. 使用 Swift 进行黑客攻击
  2. 机器人娜塔莎
  3. 中等的