【问题标题】:Why does typealiasing a tuple of a generic protocol in Swift allow me to treat it as a non-generic protocol?为什么在 Swift 中对泛型协议的元组进行类型别名处理允许我将其视为非泛型协议?
【发布时间】:2015-11-10 21:32:13
【问题描述】:

我无法理解为什么对泛型协议的元组进行类型别名处理突然允许我将其视为非泛型协议。由于 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

因为HashableEquatable 继承了Self 要求。

示例 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:

此外,1-tuple 也不起作用,不管有没有 typealias:

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 中获取先前的 typealias 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
}

谁能解释一下这里发生了什么?

【问题讨论】:

  • 绝对看起来像一个错误..

标签: swift generics swift2


【解决方案1】:
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 是空元组类型 () 的类型别名。 如果只有一个 括号内的元素,类型只是那个的类型 例如,(Int) 的类型是 Int,而不是 (Int)。作为一个 结果,只有当元组类型有两个时,才能命名元组元素 或更多元素。

这相当于你的类型别名

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

【讨论】:

  • 那句话解释了为什么示例 4 不起作用,(Hashable) 和 Hashable 之间没有区别。但我不明白你在你的代码 sn-p 中想说什么。
  • foo 是 touple 的类型。您首先创建元组 (Int, String),然后将其分配给类型为元组的变量。 Int 符合 Hashable,String 符合 Hashable,所以 (Int, String) 的类型与 foo 相同。
  • Array bar (2b) 相同。 bar 的类型为 Array.Type 元组数组
  • 想想你的 CompositeHashabe。类型是元组,其中第一个属性必须符合 Hashable,第二个属性必须符合 Hashable。所以元组。 (Int, String) 和 (Hashable, Hashable) 不一样!元组 (Int, String) 只是满足 CompositeHashable 的要求
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
相关资源
最近更新 更多