今回は継承,特に誤解されがちな多重継承について改めて解説します。「オブジェクトは現実世界のモノの反映であり,継承はそのモノの分類を反映したものである」,「多重継承は良くないものだ」という意見が正しいかどうか,判断する基準を紹介します。
今回は,オブジェクト指向にまつわる誤解を取り上げましょう。
これまで,オブジェクト指向プログラミングの古くからのファンとして解説を書き,Rubyというオブジェクト指向プログラミング言語を提供してきました。オブジェクト指向プログラミングをより多くの人が身近に感じられるように貢献してきたつもりです。Smalltalkよりも手軽に入手でき,JavaやC++よりも簡単にオブジェクト指向プログラミングを実践できるRubyによってオブジェクト指向という概念がより理解しやすくなったのではないかと自負しています。
しかし,その過程で,私自身の未熟さもあり,オブジェクト指向プログラミングに対する誤解を広げてしまったという側面もあるようです。
2つの誤解
オブジェクト指向プログラミングにまつわる誤解のうち,私が特に気にしているものは次の2つです。
一つは,「オブジェクトは現実世界のモノの反映であり,継承はそのモノの分類を反映したものである」という意見です。これは間違っています。私自身も最初の著書である『オブジェクト指向プログラミング言語Ruby』*1では,ほ乳類,犬,クジラなどを例に採ってしまったため,誤解を助長してしまったかもしれません。
もう一つは「多重継承は良くないものだ」という誤解です。これも間違いです。その上,「けれどもMix-inは悪くない」*2という誤解がセットになっていることも多いようです。
解説する前に先に正解を書いてしまうと,最初の誤解に対しては「多重継承はうまく使わないと問題が起きる(ことがある)」となります。2番目のMix-inについては「Mix-inは多重継承の使い方のテクニックの1つに過ぎない」となります。
Rubyは多重継承をMix-inという制約された形でしかサポートしていませんが,これは開発当時まだあまり知られていなかったMix-inという「テクニック」を啓蒙するのが目的で,多重継承そのものをおとしめるつもりはありませんでした。しかし,結果的に誤解を広める要因になってしまったようです。あるとき,著名な若手研究者が多重継承とMix-inは別物だと信じていらっしゃった,しかも,その原因はRubyであったのを知って,深く反省したものです。
もちろん私ばかりが原因であるなどと大それたことを考えているわけではありません。しかし,誤解を少しでも解消するために,今回はオブジェクト指向プログラミングと多重継承について再び解説します。
オブジェクト指向プログラミング
歴史的な視点を採ると「オブジェクト指向」という考え方は1960年代の末から1970年代にかけて,複数の起源から発生しました。例えば,抽象データ型の研究,人工知能の分野の知識表現(フレーム・モデル),シミュレーション対象の管理技法(Simula),並列型計算モデル(Actor),構造化プログラミングなどが相互に影響を与えあって誕生したものだと考えられています。
フレーム・モデルなどは現実世界のモデル化そのものです。この視点から見ると最初に挙げた「オブジェクトは現実世界のモノの反映である」というのは間違いではありません。
しかし,歴史はともかく現在のオブジェクト指向プログラミングを一番よく理解できる視点は,「オブジェクト指向プログラミングとは構造化プログラミングの延長だ」というとらえ方ではないかと考えます。
コンピュータの登場当初,ソフトウエアに求められる仕事は単純でした。そのため人間が作業手順をアセンブリ言語やマシン・コードを用い,プログラムとして記述するのはさほど難しいことではありませんでした。しかし,ほどなくソフトウエアは複雑化し,開発は次第に難しい仕事になってきました。これに対してEdsger Dijkstra氏*3は,制御の流れを次の3つの組み合わせに限定・単純化することで,分かりやすいプログラムが記述できると提唱しました。
(1)順次 コードの並び順に実行する
(2)反復 ある条件が成立する間,処理を繰り返す
(3)分岐 ある条件が成立するなら処理Aを,そうでなければ処理Bに進む
構造化プログラミングは基本的に制御の流れに構造をもたらすものでした。しかし,制御構造は構造化されてもデータについては十分に構造化されていたとはいえません*4。歴史はともかく,オブジェクト指向プログラミングは構造化プログラミングによって導入された制御の構造化に加えて,データの構造化を取り込んだものだと考えられます。
オブジェクト指向プログラミングに対する考え方には幅がありますが,どのオブジェクト指向言語にも共通に備わっている機能があります。