dT*blog

design and programming

Iteratorパターンはfor文じゃダメなの?

「Iteratorパターンなんて使わなくても、for文を使えば良いんじゃないの?」

煽りではなく、不意にそう思ってしまった。でも、冷静に考えると、このふたつは等価であるとは限らない。そして、反復処理をそのコレクション型クラス自体に隠蔽することに、大きな意味があるな、と思い直した。危ない、危ない。

List list = new SomeArrayClass();
for (Iterator it = list.iterator(); it.hasNext();) {
    System.out.println(it.next());
}

これを for文 で扱おうとすると、SomeArrayClass が何者かを知らないといけないので、オブジェクト間の関係が密になってしまう。その正体が何なのかを意識しなくて良いのが、iterator の良いところ。極端な例ではあるけど、これなら将来的に SomeArrayClass の内部実装が変わることに耐えられる。

そこに気付いたところで、次なる疑問。じゃあ、拡張for文とは何が違うのか。

List<String> list = new SomeArrayClass<String>();
for (String str : list) {
    System.out.println(str);
}

こう書くと、上のIteratorパターンのサンプルとまったく同じ役割を果たしてくれる。何が違うんだろうと思って探索した結果、どうやら拡張for文は内部で iterator を使っている模様。ああ、そういうことでしたか。

こういうことをキチンと踏まえた上で、敢えてIteratorパターンを用いず、for文で反復制御を書くことに意味があるんだろうなあ。

Iteratorパターンとfor文が等価ではないのは、例えば以下の場合とかだろうか。

List list = new SomeArrayClass();
for (int i = list.size() - 1; i >= 0; i--) {
    // 配列を逆順で表示
    System.out.println(list.get(i));
}

このように、特別なケースとして細かい制御を加えようとするなら、どうしてもfor文を使わざるを得ない場面というのもありうる。仕方ない場合はね。

ただ、あるクラスの管理する情報にアクセスする場合、そのクラスのインタフェースに従うのが安全。ゼロから順にインデックスをなめることに意味がない場合、よくあるfor文は、論理エラーになってしまう。そういう場合、iterator は効力を発揮するはず。

  • 自身のコレクション要素をスペル順に走査するiterator
  • 日付をインクリメントするカレンダーのiterator
  • 行列を A11 から Aij まで順に走査するiterator

この例だと、ユーティリティ的な色合いが強い反復子のようだけど、こういう iterator が無いと意味をなさないクラスがある。集約オブジェクトに対するアクセス法としてIteratorパターンを考えれば、こういうのもアリかと。

そういうことで、Iteratorパターンはfor文では置き換えがたいケースがあるということで終わり。まあ、保守性があって安全に動けば、もう何でも良いや。

Posted by dT by 02:40

トラックバック

このエントリーのトラックバックURL
http://www.deftrash.com/admin/mt/mt-tb.cgi/321

コメント




保存しますか?

(書式を変更するような一部のHTMLタグを使うことができます)

  • 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