【问题标题】:Swift: What is the difference between a typealias and an associatedtype with a value in a protocol?斯威夫特:类型别名和关联类型与协议中的值有什么区别?
【发布时间】:2019-09-01 11:28:21
【问题描述】:

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

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}

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

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

为清楚起见进行编辑:

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

【问题讨论】:

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


    【解决方案1】:

    在您编写的代码中并没有真正的功能差异,因为您将associatedtype 设置为Int

    要从它们中获得更强大的用法,您可以使用 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]
    }
    

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

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

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

    并将所有用法替换为DownloadResponse

    在 Swift 中有大量关于 associatedtype 的优秀资源...

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

    【讨论】:

    • 我知道如何将关联类型用于常规目的,但我想知道在这种特殊情况下有什么区别。我很惊讶您甚至可以将关联类型分配给一个值,因为这看起来与关联类型应该做的完全不同。 P1 和 P2 之间一定有一些区别,因为只有 P1 对具有关联类型的协议进行了通常的限制。我想知道是否还有其他差异——比如协议方法是如何分派的等等。
    猜你喜欢
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多