この忙しいのに日記を毎日更新なんてしていられません。あきらめます。今日だって、こんなことをやっている間にどんどん帰る時間が遅れていくのだ。なぜそうまでして日記を書くのだろう。
今日は久々に調子が良かった。使おうとしているシミュレータ、使い方がさっぱり分からず、仕方がないからソースコードを1から全部見直していたところ、なんとインターフェースが用意されていたのだ。知りたい情報も関数一発。…なぜ今まで気づかなかったのだろう。ただ、純粋仮想関数が40ばかしあってオーバーライドが面倒だ。
純粋仮想関数とは、Javaで言う抽象メソッドだ。名前がついているからやることはだいたい分かるのだが、その内容がまったく記述されていない関数を指す。こいつの存在意義を理解したらオブジェクト指向の第一歩を踏み出したと言っていいと思う。
オブジェクト指向の根底にあるのは、何度も同じことをしたくないという、言ってみれば手抜きの発想だ。で、同じようなプログラムを何回も書く可能性がある場合、そいつに対して名前をつけておく。そして、必要に応じてそいつを拡張するのだ。こうすることによって、他の場所を変更することなくいくらでも拡張することが可能になる。もしこの機能がなかった場合、1つの関数を別の関数を変更するときに、呼び出し側も変更しなければならない。100箇所から呼ばれている関数の場合は100箇所書き換えなければならない。時と場合によって古いほうと新しいほうのどちらを呼ぶか分からない場合はその状況に応じて一つ一つの関数を変更するかしないか決めなければならない。どちらを呼ぶか分からないなら同じ名前じゃ困るじゃないかと言われそうだが、実は、同じ名前に複数の機能を持たせることができるのが、この仮想関数、もしくは抽象メソッドの効果なのだ。Javaの方が好きなのでJavaの用語で例を挙げると、自動車という抽象クラスがあって、そこにメーカー名を取得する抽象メソッドがあったとする。そして、自動車クラスを継承して、トヨタクラスと日産クラスを作る。トヨタ車クラスのメーカー名はトヨタであり、日産車クラスのメーカー名は日産だ。で、自動車クラスのオブジェクトを宣言し、その実態はトヨタ車のオブジェクトであるとする。コードで書くとCar car = new ToyotaCar();
って感じだ。…もはや誰にも理解できない文章だがまあ、いいか。んで、この車に対してメーカー名を問い合わせる。car.getMakerName();
って感じだろうか。すると、そいつはトヨタだと言ってくる。次に、そのオブジェクトの実態を変更する。車であればなんでもいいので変更しても構わないのだ。car = new NissanCar();
という感じだろうか。で、そいつに向かってメーカー名を問い合わせる。car.getMakerName();
となる。ここで重要なのは、トヨタ車に対してメーカー名を問い合わせたときと、構文がまったく同じだということだ。これによって、carの実態は置いといて、メーカー名を問い合わせるという作業に集中できる。16世紀あたりに、すでに言われているではないか。「困難は分割せよ」と。車の実態とメーカー名を問い合わせる機能を別々にすることで、複雑になることを避けようとしているのだ。車がなんであっても、プログラムを書くときはcar.getMakerName();
と書けばメーカー名が分かる。もし使いこなせれば便利だ。
で、最初の話に戻ると、僕が使おうとしているシミュレータには、このような抽象的な関数が40ほど定義されていたのだ。この中身をちゃんと書いておかないと、メーカー名を聞かれても分からないということになってしまう。必要な部分は一部だが、全部やれと言われているのだから仕方がない。明日にでもすべて実装することにする。ちなみに、僕が実装しなければならない純粋仮想関数は全部で41個だが、それ以外にもそのインターフェースには関数が多数定義されていて、すべて合わせると90個になる。きちんと文書に目を通しておかなければ。文書の内容とソースコードに食い違いがあるからその点も十分に注意しなければ。Windows対応にしなければならないということでおかしくなってきたようだ。ちなみに、上位のクラスで定義されている関数、もしくはメソッドを下位のクラスで定義しなおすことをオーバーライドという。名前が同じで引数が異なる関数、もしくはメソッドを定義するのはオーバーロードと言ってまったく別物だ。オーバーロードの場合は上位、下位のクラスである必然性はなく、そもそもクラスでなくてもいい。同じものを書き直すのがオーバーライドであり、オーバーロードは名前が同じなだけでそもそも別なのだ。
きっと、あとで自分が読んでも分かるまい。まあ、書いてて楽しいからそれでいいのだ。で、どんどん帰るのが遅れると。やれやれである。