让我们从IteratorProtocol.next的实现开始。编译器看到这个实现:
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
并注意到它返回一个Int?。好吧,IteratorProtocol.next 应该返回一个Self.Element?,所以它推断出IteratorProtocol.Element == Int。现在Coundown 满足IteratorProtocol。
注意Sequence 和IteratorProtocol 共享 关联类型Element。一旦 Swift 找出了 IteratorProtcol.Element 的见证人,就好像你在 Countdown 中声明了一个新的类型别名 Element,而 Sequence 恰好要求 Countdown.Element 存在。
之后,编译器推断Iterator == Self。这样makeIterator 的默认实现就可用了。然而,编译器如何推断这一点却是一个谜,因为只有这些信息,通常无法推断出类型,这可以通过创建自己的序列和迭代器协议来证明。
protocol MyIterator {
associatedtype Element
mutating func next() -> Element?
}
protocol MySequence {
associatedtype Element where Element == Iterator.Element
associatedtype Iterator : MyIterator
func makeIterator() -> Iterator
}
extension MySequence where Self == Self.Iterator {
func makeIterator() -> Iterator {
return self
}
}
struct Countdown: MySequence, MyIterator { // doesn't compile
var count: Int
mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
}
在查看source code 之后,我怀疑可能有一些编译器魔法正在发生,尤其是这里:
// Provides a default associated type witness for Iterator when the
// Self type is both a Sequence and an Iterator.
extension Sequence where Self: IteratorProtocol {
// @_implements(Sequence, Iterator)
public typealias _Default_Iterator = Self
}
这似乎为Iterator 设置了一个“首选”类型来推断为。它似乎在说“当Iterator 不能被推断为任何东西时,试试Self”。我在其他任何地方都找不到_Default_Iterator,这就是为什么我断定它是编译器的魔法。这样做的全部目的是让您通过仅符合IteratorProtocol 并实现next 来符合Sequence,就像documentation 所说的那样。
现在有了Iterator == Self,我们也满足了Element的约束:
associatedtype Element where Self.Element == Self.Iterator.Element
因此我们已经证明Countdown 符合Sequence。