swift - 为什么在 Swift 中对泛型协议(protocol)的元组进行类型别名允许我将其视为非泛型协议(protocol)?

标签 swift generics swift2

我无法理解为什么对通用协议(protocol)的元组进行类型别名突然允许我将其视为非通用协议(protocol)。由于 Swift 泛型的工作方式,我们预计会在示例 1、3、4 和 5 中遇到错误。但是为什么示例 2 可以工作?它与示例 3 在语义上有何不同?

示例 1:

正如预期的那样,这不会编译:

let foo: Hashable = "a" // error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

因为 Hashable 继承了 EquatableSelf 要求。

示例 2:

但是如果我定义一个 Hashable 的元组,它就可以工作了!

typealias CompositeHashable = (Hashable, Hashable)
let foo: CompositeHashable = (1, "a") // This works!

现在我不再需要使用 Hashable 作为通用约束。

示例 2b:

我什至可以在集合中使用 CompositeHashable:

let bar: [CompositeHashable] = [(1, "a"), ("b", "a")] // This works!

示例 3:

有趣的是,如果我不为元组输入别名,它就不起作用。

let foo: (Hashable, Hashable) = (1, "a") // error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

这应该等同于示例 2,对吧?

示例 4:

此外,无论有无类型别名,一元组都不起作用:

typealias HashableTuple = (Hashable)
let foo: HashableTuple = ("a") // error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

示例 5:

还有一点……如果我从示例 2 中获取之前的类型别名 CompositeHashable,并将其简单地移动到一个结构中,它现在会给出我们在其他情况下预期的相同错误。

struct CompositeKey {
    typealias CompositeHashable = (Hashable, Hashable) // error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements
}

谁能解释一下这是怎么回事?

最佳答案

typealias CompositeHashable = (Hashable, Hashable)
CompositeHashable.self

// it is OK !!!!!

let foo: CompositeHashable = (1, "a") // This works!
foo.0.dynamicType   // Int.Type
foo.1.dynamicType   // String.Type
foo.dynamicType     // (Hashable, Hashable).Type

Any.self            // protocol<>.Protocol

let bar: [CompositeHashable] = [(1, "a"), ("b", "a")]
bar.dynamicType // Array<(Hashable, Hashable)>.Type    Hashable.self // error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements

.... 这个很有趣

let foo: HashableTuple = ("a")

Void is a typealias for the empty tuple type, (). If there is only one element inside the parentheses, the type is simply the type of that element. For example, the type of (Int) is Int, not (Int). As a result, you can name a tuple element only when the tuple type has two or more elements.

这相当于你的类型别名

let (a,b) = ("a",1)
typealias Htuple = (A:Hashable,B:Hashable)
let t:Htuple = (a,b)

关于swift - 为什么在 Swift 中对泛型协议(protocol)的元组进行类型别名允许我将其视为非泛型协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33640000/

相关文章:

ios - 在 Customize UIView 上添加 subview 效果不如预期

c++ - 模板类类型仅适用于基本类型,不适用于类类型

ios - 动画 View 跳转到最终位置而不是缓慢移动

ios - 依次执行Dispatch main

ios - Facebook 登录用户数据未显示在 firebase 控制台中

java - 是否可以创建一个在运行时反射(reflect)类的 List<class> ?

ios - 使用 RealmSwift 将 Realm 对象与 iOS 9 中的 UITabBarController 相关联

ios - 如何使用 Swift 在 ios 中关闭 viewController

ios - 生成敌人在 spritekit/swift 中效果不佳

c# - 实现通用接口(interface)的类的字典