今回は、IteratorパターンのCocoaでの実例を取り上げる。Iteratorパターンは、多くのプログラマにとって馴染みの深いものだろう。Cocoaでも、大変よく使われるIteratorパターンのクラスがある。NSEnumeratorだ。
NSEnumeratorのメソッド
Iteratorパターンを使う上で重要なのは、オブジェクトを順繰りに取得するために、どんなメソッドが提供されているかということだ。前回紹介したGoF本の例では、First()、Next()、IsDone()、CurrentItem()の4つのメソッドがあった。
NSEnumeratorでは、2つのメソッドが提供されている。だが、実際に使うことになるのは1つだけだ。nextObjectというメソッドである。
List 1. NSEnumerator.h
- (id)nextObject;
このメソッドを呼ぶと、「次の」オブジェクトを取得することができる。つまり、参照位置を1つ動かして、そこにあるオブジェクトを返す訳だ。GoFの例で言うと、Next()とCurrentItem()を組み合わせたものになる。集合の最後まで行くと、nilを返す。これを、IsDone()の代わりに使うことになる。
NSEnumeratorを使う、典型的なソースコードを示そう。
List 2.
NSENumerator* enumerator;
id object;
// enumeratorを取得する
...
while (object = [enumerator nextObject]) {
// objectに対する処理
}
while文を使ってループを回すのだが、その条件文の中にnextObjectの呼び出しを入れてしまうのである。これで何らかのオブジェクトが返ってくれば、続けて処理を行う。集合の最後に到達してnilが返ってきた場合は、whileループが終了する。これで、集合のオブジェクトをすべて走査する事ができる。
ちなみに、NSEnumeratorのもう1つのメソッドはallObjectsというもので、すべてのオブジェクトを取得するためのものだ。
NSEnumeratorを取得する
Cocoaでは主なコレクションクラスとして、配列を表すNSArray、辞書(または連想配列)を表すNSDictionary、順序無しの集合を表すNSSetなどが提供されている。これらからNSEnumeratorを取り出すメソッドを紹介しよう。
まずNSArrayでは、通常のIteratorをobjectEnumeratorで取得できる。また、最後尾から逆向きに走査するIteratorのためにreverseObjectEnumeratorというメソッドもある。
List 3. NSArray.h
- (NSEnumerator*)objectEnumerator;
- (NSEnumerator*)reverseObjectEnumerator;
NSDictionaryでは、キーと値のペアでオブジェクトの集合を作るのだが、キーを走査するためのkeyEnumerator、値を走査するためのobjectEnumeratorというメソッドがある。
List 4. NSDictionary.h
- (NSEnumerator*)keyEnumerator;
- (NSEnumerator*)objectEnumerator;
最後にNSSetだが、NSArrayと同様にobjectEnumeratorというメソッドを使う。
List 5. NSSet.h
- (NSEnumerator*)objectEnumerator;
これらのメソッドから取得したNSEnumeratorで、コレクションクラスに含まれるオブジェクトの集合を走査できるのだ。
ファイルツリー探索のIterator
バリエーションも紹介しよう。NSEnumeratorのサブクラスには、NSDirectoryEnumeratorというものがある。これは、ファイルツリーを走査するためのIteratorだ。
このオブジェクトは、NSFileManagerというファイル管理のためのクラスから取得できる。enumeratorAtPath:というメソッドを使う。
List 6. NSFileManager.h
- (NSDirectoryEnumerator*)enumeratorAtPath:(NSString*)path;
pathで指定したパスの、サブパスを走査できる訳だ。使い方は、次のようになる。
List 7.
NSDirectoryEnumerator* enumerator;
NSString* subPath;
enumerator = [[NSFileManager defaultManager] enumeratorAtPath:@"/Users/mkino"];
while (subPath = [enumerator nextObject]) {
....
}
これで、ファイルの集合に対しても、同じAPIで走査できるようになる。Iteratorパターンの柔軟性を示すいい例だろう。
効率よくNSEnumeratorを書く
このNSEnumeratorはCocoaプログラミングをしていると非常に頻繁に使用するのだが、正直言って書くのが面倒に感じることもある。タイプ数が多いのだ。近年のプログラミング言語を見ると、Iteratorパターンを言語の文法の中に組み込んでおり、少ないタイプ数で効率よく書けている。
LeopardことMac OS X 10.5では、Objective-C 2.0と呼ばれる文法の拡張が行われるが、AppleのLeopard紹介によると、Objective-C 2.0には「fast enumeration」のための文法の拡張が行われるようだ。
詳細はまだ論ずることはできないが、Objective-Cでも効率のいいIteratorを書く事ができるようだ。近い将来あるであろう、Objective-C 2.0の公開が待たれるところである。
提供:毎日キャリアバン ク
毎日キャリアバンクではITエンジニア出身のキャリアコンサルタントで形成する IT専門のチームを編成し、キャリアに応じた専任コンサルタントがご相談を承り ます。キャリアチェンジから市場価値の可能性、ご収入などの相談から面接のア ドバイスまでお気軽にご相談ください。求人情報誌や転職情報サイトなどで一般 に公開されていないような「急募求人案件」も随時ご紹介が可能です。まずはご 登録ください!