Java.use(better); Episode#01 拡張可能な for 文(1)
《目的》
オブジェクト指向プログラミングの障害となる「古典的な for 文」の隘路を確認した後で「拡張 for 文」による問題解決を図るとともに、制御構造を抽象化して「ポリモフィズム」を促進する術を紹介します。
《動機》
J2SE 5.0(2004年)から導入された「拡張 for 文」は、ともすると、同じ綴りの古典的な for 文と同列に比較されがちです。しかし、プログラミングの立場からすると、これらには雲泥の開きがあります。古典的な for 文は、SP の三本柱のひとつ「反復」構造を支援します。拡張 for 文は、OOP の三本柱のひとつ「ポリモフィズム」を支援します。また、拡張 for 文の特性を利用して「制御構造の抽象化」を実現できます。これにより、遅ればせながら Java も、先行する Jython/Scala などと肩を並べて、より本格的なオブジェクト指向プログラミングの醍醐味を堪能できます。
■ 構造化プログラミングの隘路
数学者 Karl Friedrich Gauss (1777-1855) が神童と呼ばれた、幼少期のエピソードとして有名な「1 から 100 までの総和」を事例に話を進めます。以下の事例では、1 から 100 までの要素を列挙した、seq が存在するものとします。
構造化プログラミングにおける三種の神器(連接/選択/反復)の中から、この問題解決に必要なのは何でしょう。それは、for/while などの「条件反復」です。そこでは、任意の条件式を満たすかぎり、同じ処理を繰り返すという流れに沿って、データ構造とアルゴリズムが確定します。
まず、データ構造に ArrayList を選ぶと、それに最適なアルゴリズムが確定します。すると、
// case #1: Java 流 - 構造化プログラミング int sum = 0; ArrayLists = new ArrayList (seq); for (int i = 0; i < s.size(); i++) { sum += s.get(i); } System.out.println("sum = "+sum);
変数 i は、添字〔= index〕を意味します。各要素を巡回するには、メソッド get(i) を利用しながら、次の要素 i++ に歩を進めます。このとき、プログラマーは、添字は 0 から始まるとか、配列の長さ(大きさ)を超えないようにとかに、細心の注意を払う必要があって`憂鬱`です。
次に、データ構造に LinkedList を選ぶと、
// case #2: Java 流 - 構造化プログラミング int sum = 0; LinkedLists = new LinkedList (seq); while (s.size() > 0) { sum += s.remove(); } System.out.println("sum = "+sum);
各要素を巡回するには、メソッド remove() を利用しながら、次の要素に歩を進めます。ここでも、プログラマーは、残された要素はあるのかとか、リストの要素を取り出すにはとかに、細心の注意を払う必要があって`憂鬱`です。
この問題は深刻です。というのも、データ構造(配列/リストなど)に依存するかぎり、同じ制御構造を何度も記述する必要があるからです。さっきも同じコードを書いたことがある。この次も同じコードを書くことになる。そのツケは「メンテナンスの悪夢」として、やがてプログラマーが清算する羽目になります。
データ構造に依存しない制御構造を再利用する術が必要です。それを可能にするのが、オブジェクト指向プログラミング/関数型プログラミングです。
↑ TOP
♪ 葭原雀(よしわらすずめ)