自作クラスをfor...inで使う
Swiftでコレクションクラスを見て、自分でもちょっと試してみた。
for item in collection {
statements
}
「The Swift Programming Language」によると、For-In Statement中の,
collectionはSequnceプロトコルを実装した型であるらしい。
Sequenceプロトコルは、
・メソッドgenerateを持ち、
・メソッドgenerateは”Generatorプロトコルを実装した型”のオブジェクトを返す。
また、Generatorプロトコルは”nextメソッドを持つ型”のようだ。
メソッドnextは、
・返す要素が無くなればnilを、
・それ以外のときには、それなりのオブジェクトを返せばよさそうだ。
Generatorプロトコル
整数を1から10まで返すクラスを例に、
Generatorプロトコルを持つクラスのほうを書いてみる。
class Foo : Generator {
var count = 0
func next() -> Int? {
if self.count < 10 {
self.count++
return count
}
return nil
}
}
Generatorプロトコルは、nextメソッドを持つ(らしい)。
また、nextメソッドの返り値は、ループが終わりの場合にはnilを、
それ以外のときにはnext()の宣言のときに宣言した型(上記の例ではInt)の値を返す。
Sequenceプロトコル
次に、Sequenceプロトコルのほうを考えてみる。
class Bar : Sequence {
func generate() -> Foo {
return Foo()
}
}
こちらは、generateメソッドを持つ(ようだ)。
generateの戻り値の型は、Generatorプロトコルを持つなんらかの型である必要がある。
ここでは、さきほど定義したクラスFooのオブジェクトを返している。
使い方
ここまで用意できたら、あとは下記のようにSequenceプロトコルを持つオブジェクトを
for...inで使えばよい。
var bar = Bar()
for item in bar {
println(item)
}
補足
Sequenceプロトコルを実装したクラスはコードも短いので、
Generatorプロトコルも一緒に実装してしまうのも1つの手だと思われる。
蛇足
ここまでのコードはすべて1つのファイルに書いてみたが、普通に動作した。