この題名を見て何のことか分かったなら、その人はおそらくプログラムをある程度書いたことがある人だろう。僕が真剣に考えるようになったのはつい最近のことだが。
オブジェクト指向のプログラムというのがある。現実世界の感覚をいかにしてそのままコンピュータの世界に持ち込むかという難題に対して、一つの答えを示したものだ。かなり有効な答えらしく、今じゃ常識のように言われている。とにかく、コンピュータのことは置いておいて、物事を必要に応じて切り分けて、その性質と機能を一つ一つ考えていくのだ。自動車は乗り物の一種であって、タイヤがあってハンドルがあって、アクセルを踏むと走って…。ってな感じだ。どんどん細かくしていけば、いずれプログラムにすることができる。もちろん、自動車そのものができるわけではないから、なにを表現して何を表現しないのかは考える必要がある。何らかの変数を用意して、これは自動車の速度である、としてしまったりするのだ。
で、そういうオブジェクトを考えると、次に問題になってくるのがそのオブジェクト同士の関係である。ものは1つあったところで限られたことしかできない。多種多様なものがあって、それがいろいろと関係しているから多くのことができるのだ。あるもの、例えばまた自動車を挙げると、その中にはタイヤというものもあるし、ハンドルというものもある、というように、どんどん切り分けることもできる。あるいは、乗り物というもの、というように抽象化することもできる。1つのものに対していろいろな見方をしたとき、そこから新しいものが作り出せるのだ。
で、そのものとものとの関係の中に、継承という関係と委譲という関係がある。継承のほうが、おそらく考え方はシンプルだ。自動車は乗り物である。これは、自動車は乗り物の1つである、とも言える。乗り物はいろいろあるが、その中の1つが自動車であり、自動車ならば必ず乗り物である。このとき、自動車が乗り物であるなら、乗り物に共通する普遍的な性質、例えば人や物を乗せることができるとか、移動できるとか、そういうことは自動車にも言えるはずだ。ここから、乗り物の性質と機能を自動車にも受け継がせようとするのが継承である。一方委譲とは、機能を他人任せにすることだ。これはどうもオブジェクト指向の初期の頃にはなかった考えらしいのだが、自動車にはエンジンがある。自動車はエンジンを持っていると言ってもいい。で、エンジンは自動車ではない。エンジンは自動車のパーツではあるが、自動車そのものではない。こういうときに委譲という概念が登場するのだ。つまり、自動車の一部分をオブジェクトとして考えるのだ。こうすると、自動車から見た場合、自動車はエンジンを持っているとだけ考えればいい。エンジンがどう動くかはそのエンジンに任せることができる。このように他人任せにする発想法を委譲というのだ。
それだけ考えると、継承は自然な発想で委譲は面倒な考え方に見えるかもしれない。乗り物に共通の性質を自動車も持っていると考えれば、乗り物を考えてから自動車を考えるとき、乗り物のところですでに考えたことは自動車について考える必要がない。自動車も乗り物なんだから、共通の性質については同じことが言えると言ってしまえば終わりなのだ。一方委譲の場合、自動車を作るときにエンジンの動きも一緒に作ってしまえばいいと思える。継承と違って、他人任せにしても自分でやっても、やることは変わらないどころか、むしろ別々になったことでやることが増えてしまう。
しかし、継承には弱点があって、委譲はそれと同じ点を長所として見ることができるのだ。それが、複雑さの問題だ。1回くらいの継承ならたいしたことはないが、これが何回も繰り返されたり複雑な継承をすると、どの性質がどこから受け継がれてきたかさっぱり分からなくなるのだ。はげてしまったのは父方の先祖のせいか母方の先祖のせいか、あるいは父方の父方か、父方の母方か、などと延々追い続けるようなものだ。それが委譲の場合になると、逆に物事は単純化する。自動車は走る。どう走るのかはエンジンの性能による。あとはエンジン任せで俺は知らないよ、となるから自動車そのものは簡単になる。一方でエンジンのほうも、俺は燃料を食ってアクセルの指示に従って回る。ハンドルさばきなんて興味ないよ、となる。それぞれのやることが単純化するのだ。もちろん、先ほど述べたように、あまりにバラバラにしすぎるとやることが増えてしまうわけだが。でも、基本的には単純化しているので、どれほどバラバラにしても、バラバラにしないときより分かりづらくなることはあまりない。
ということで、理想を言えば継承がいいのだが、現実的に考えた場合、継承はその関係を追いきれない。だからなるべく委譲を利用するのがよいとされている。継承と委譲では適用できる場面が違うので、委譲を適用できるように問題の状況からオブジェクトを拾い出すのだ。つまり、何かがあって、その何かはこんなパーツで構成されている、と表現するようにするのだ。ただ、ほとんどのプログラミング言語は継承を明示的にサポートしているが、委譲を明示的にサポートしていない。継承専用の文法はあるが、委譲の場合は普通の変数代入を応用して、オブジェクトの代入という形でやることになる。オブジェクトがオブジェクトを持っているから、仕事をその持っているオブジェクトに投げてしまうことができるのだ。ってなわけで継承も十分扱いやすい。結局のところ、時と場合に応じて使い分けることになるのだろう。だからこそ僕も、今、どちらを使うべきか悩んでいるのだ。物事の構造としては継承の関係に近い。しかし、すでに継承を繰り返してわけが分からなくなっているシミュレーションシステムが目の前にあり、僕はこれからそのシミュレーションシステムに自分のプログラムを組み込んでいくことになる。果たしてそんな状況の中、継承を使っていいのかどうか。まあ、世の中には偉い人がいて、よくあるパターンをまとめてくれた人がいる。デザインパターンというものだ。とりあえずはそれでも勉強して、参考になるかどうか確認してみよう。まあ、先日も挙げたことなのだが、やはりこのデザインパターン、それなりに難しい…。やはり、易しい解説書を購入してよかった。もっとも、今日図書館に行ったらまったく同じ本が置いてあったりしたのだが。…世の中、そういうこともあるさ。いい本なら、たとえ図書館にあったって買うべきなのさ。…3600円も出して買う価値があったのかどうか、正直言って微妙な気分だが。とりあえずは全部読んでから考えよう。いや、デザインパターンの本なんて、擦り切れるまで読むべきだ。そうだ。そうに違いない。
それにしてもC++か…。C++からJavaならよかったのだろうが、逆は少々つらいものがある。C++はJavaよりもはるかにコンピュータに近く、行動の自由度が大きいのだ。それはよいことでもあるのかもしれないが、何が起こるか想像もつかないということにもなる。その点Javaは仮想マシンという架空のコンピュータ上で動くもので、その行動パターンは高が知れている。正常に動作するか、なんらかの例外を投げるかくらいしかパターンがない。メモリを読みすぎて意味不明の動作をするとか、確保したメモリを開放し忘れていつの間にか莫大な量のメモリを一人で使っていたとか、そういうことはほとんど起こらない。意図的に書けばもちろん別だし、時と場合によっては起こりうるのだが。まあ、使いづらい言語を使うのも1つの勉強だ。それに、将来はC++も使う機会があるだろう。逆にJavaはこれから先、暗い未来が待ち構えているのかもしれないし。