今天看到Array 的API中有這麼一個聲明的函數:
mutating func extend<S : SequenceType where T == T>(newElements: S)
函數名爲extend, 所需參數是S類型的newElements, 而S首先要實現SequenceType協議。那SequenceType到底是什麼呢?
官方對SequenceType的聲明API如下:
protocol SequenceType : _Sequence_Type {
/// A type that provides the *sequence*\ 's iteration interface and
/// encapsulates its iteration state.
typealias Generator : GeneratorType
/// Return a *generator* over the elements of this *sequence*.
///
/// Complexity: O(1)
func generate() -> Generator
}
裏面需要實現一個函數generate(),返回了一個GeneratorType類型,GeneratorType又是什麼呢?看看APT
protocol GeneratorType {
/// The type of element generated by `self`.
typealias Element
/// Advance to the next element and return it, or `nil` if no next
/// element exists.
///
/// Requires: `next()` has not been applied to a copy of `self`
/// since the copy was made, and no preceding call to `self.next()`
/// has returned `nil`. Specific implementations of this protocol
/// are encouraged to respond to violations of this requirement by
/// calling `preconditionFailure("...")`.
mutating func next() -> Element?
}
GeneratorType必須要實現一個函數next(),它的作用就是返回一個Element,註釋裏說的很清楚:它的作用就是一直返回元素,直到最後。
具體怎麼用呢,咱們從for...in...來了解下:
首先讓我們先來看一下常見的這個遍歷方法:
for x in mySequence {
// iterations here
}
而Swift實際上是按照下面這個方法來實現的:
var __g: Generator = mySequence.generate()
while let x = __g.next() {
// iterations here
}
這是什麼意思呢?
1)Swift調用generate()來生成了一個Generator,這個對象是 一個私有的變量即__g;
2) __g調用了next()函數,返回了一個optional類型對象element?。這個對象element被解包後賦值給了x;
3)通過next()函數一直來獲取下一個元素,直到爲nil停止。
所以,要實現Sequence必須要先有一個Generator。如下面的例子是對數組進行倒序索引:
1) 先聲明繼承與GeneratorType的類,實現Element和next()
///GeneratorType
class CountdownGenerator: GeneratorType {
typealias Element = Int
var element: Element
init<T>(array: [T]){
self.element = array.count - 1
}
func next() -> Element? {
return self.element < 0 ? nil : element--
}
}
2)完成繼承於SequenceType的類,實現Generator和generate()
class ReverseSequence<T>: SequenceType {
typealias Generator = CountdownGenerator
var array: [T]
init(array: [T]){
self.array = array
}
func generate() -> Generator {
return CountdownGenerator(array: array)
}
}
3)使用:
let array = ["a", "b", "c"]
for i in ReverseSequence(array: array){
println("索引\(i)的值是:\(array[i])")
}
結果:
索引2的值是:c
索引1的值是:b
索引0的值是:a
參考資料:http://segmentfault.com/a/1190000002464158
Generator