Swift标准库:Sequence协议

Sequence 协议为类型提供了迭代访问的能力,凡是实现了 Sequence 的类型,都快进行迭代访问,即使用for-in语句进行访问,标准库中的Array, Dictionary, Set等类型都实现了 Sequence 协议。下面介绍一下自定义类型如何实现 Sequence 协议。

实现 Sequence 协议的集合有以下两个特点:

  1. 集合的个数可以是有限的也可以是无限的
  2. 只能迭代一次
1
2
3
4
5
6
7
8
9
10
11
12
struct Countdown: Sequence, IteratorProtocol {
var count: Int

mutating func next() -> Int? {
if count == 0 {
return nil
} else {
defer { count -= 1 }
return count
}
}
}

使用的时候就可以使用for-in语句:

1
2
3
4
let threeToGo = Countdown(count: 3)
for i in threeToGo {
print(i)
}

对于更为复杂的例子,需要实现自定义的Iterator,下面的例子中实现了一个自定义的链表,并且自定义了迭代器LinkedListIterator,这样链表就可以使用for-in语句进行访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class LinkedList<E: Equatable> {
class Node {
public var e: E?;
public var next: Node?;
init(e: E?, next: Node?) {
self.e = e
self.next = next
}
}

struct LinkedListIterator: IteratorProtocol {
typealias Element = E
var head: Node?
mutating func next() -> E? {
if let next = head?.next {
defer { head = head?.next }
return next.e
} else {
return nil
}
}
}

private var dummyHead: Node?
private var size: Int

init() {
dummyHead = Node.init()
size = 0
}

// other method...

}

// 实现Sequence协议
extension LinkedList: Sequence {
__consuming func makeIterator() -> LinkedListIterator {
return LinkedListIterator(head: self.dummyHead)
}
}

let list = LinkList<Int>(arrayLiteral: 1, 2, 3, 4)
for item in list {
print(item)
}

参考资料:

Sequence
Everything You Ever Wanted to Know on Sequence & Collection