斯威夫特:类型别名和具有协议值的关联类型之间有什么区别?

时间:2019-04-10 22:26:18

标签: swift swift-protocols type-alias associated-types

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

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}

在我看来,它们的行为几乎相同。我注意到的唯一区别是,P1的使用时间还有其他限制,因为它具有关联的类型。特别是let x: P1是错误,而let x: P2很好。

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

为清楚起见进行编辑:

我知道关联类型和类型别名之间的有效区别,所以令我惊讶的是,甚至允许您为关联类型提供固定值。这似乎破坏了关联类型的全部目的。我想知道是否有任何实用程序可以为关联类型赋予固定值,并且我想知道一旦编译后这两个协议是否不同。

1 个答案:

答案 0 :(得分:2)

在您编写的代码中,实际上没有功能上的区别,因为您将associatedType设置为Int

要获得更强大的用法,您可以将associatedType用作伪通用约束。

所以您可以这样写...

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

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

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

struct StructWithInts: P1 {
    var itemArray: [Int]
}

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

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

typealias DownloadResponse = (Data?, Error?, URLResponse) -> ()

,并将所有用法替换为DownloadResponse

在Swift中,有很多关于relatedType的优秀资源...

  1. Hacking With Swift
  2. Natasha the Robot
  3. Medium