本書はTADS製作者用手引きの一部です。
Copyright (C) 1987 - 2000 by
Michael J. Roberts. All rights reserved.
第2章
だいたい1985年頃でしたが、ソフトウェア・マーケティング業界は「オブジェクト指向」という用語を発見し、「ハイパーテキスト」「マルチメディア」でさえまだこれから獲得しなければならない信仰心を持ってこの流行文句にしがみつきました。市場関係者がこの言葉をこぞって使う一方で、その意味を理解している人はわずかだったため、「オブジェクト指向」はほとんどあらゆるものを指すようになり、結局なにも意味しない言葉になってしまいました。
そんな混乱にもかかわらず、この言葉は確かにある意味を持っています。このセクションではオブジェクト指向プログラミングとは何か、そしてそれがいかにTADSに適用されているのかを明らかにしようと思います。本章はまたオブジェクト指向言語がなぜアドベンチャーの製作に望ましいのかも説明します。
このセクションはTADSの学習上「必読」ではありません。しかし、このシステムに影響を与えたいくつかの概念の理解を助けるでしょう。この製作者用手引きを初めて読む時にはこの章を飛ばして、言語の全体を理解した後にここに戻って来るようにしてもかまいません。
TADSはオブジェクト指向プログラミング言語です。オブジェクト指向言語は多くの点でCやPascalのような「手続き型」言語と似ていますが、違った視点から問題解決を図ります。視点の転換のおかげで、オブジェクト指向プログラミングは多種多様なアプリケーションにおいて効果を発揮しますが、特にシミュレーションに向いています。テキストアドベンチャーというのは基本的にシミュレーションです。
オブジェクト指向プログラミングの「新しい視点」とはなんなのでしょう? 基本的に、それはデータをとらえる見方です。従来の言語では、データ集合に適用される手続きの連続を書きます。コードとデータはしっかり分かれています。一方、オブジェクト指向プログラミングでは、問題を「オブジェクト」と呼ばれる実体のセットに分割します。各オブジェクトはデータと、自身の状態と振る舞いを述べるコードの両方を含んでいます。シミュレーションでは、プログラム中のオブジェクトは通常シミュレートされるオブジェクトに直接相当します。
色々な種類の跳ね回るボールに関わる物理問題のシミュレーションを考えてみましょう。従来の言語では、ボール毎に一式のデータ(位置、質量、速度など)を定義するでしょう。そして、各ボールを区別するために一種の標識(おそらく配列を用意して、インデックスの数字を使う)を与え、最後にbounceというサブルーチンが書かれ、そのサブルーチンがボールの数字をパラメータとして受け取り、ボールのデータに適切な変化を加えるということになります。
反対に、オブジェクト指向のプログラムはそれぞれのボールをオブジェクトとしてモデル化します。ボールに関するデータがボールを表現するオブジェクトの中に含まれるだけでなく、様々な相互作用下でのボールの運動を記述するのに必要なコードも同じくそのオブジェクトに含まれるのです。したがって、各ボールはそれぞれのbounceメソッド(サブルーチンに相当するオブジェクト指向用語で、ある特定のオブジェクトまたは複数のオブジェクトの集合と結び付いている)を持つことになります。bounceサブルーチンをball 3を指定する引数によって呼び出すのではなく、ball 3に向けて跳ねるようメッセージを送るのです。(「メッセージを送る」はメソッドの呼び出しを表わすオブジェクト指向用語です)
これは大量のコーディング、それぞれのボールについて同じサブルーチンを書く事態を想起させるかもしれません。幸いなことに、オブジェクト指向言語にはこういう複写を回避させる特長があります。この特長こそ継承です。あるオブジェクトを特定のクラスに属しているように定義することができ、それによりそのクラスについて定義されているすべてのコードとデータを受け継ぎます。もちろん、自身でコードとデータを定義して継承した属性に追加をしたり変更したりすることも相変わらずできます。あるオブジェクトがそのクラスによってすでに定義済みのコードとデータを定義した場合、オブジェクトが行った定義は、クラスから継承したものをオーバーライドします。
継承とオーバーライドが便利なのは、それによって一般的および特別な事例を簡潔に表現できるからです。たとえば、同質のボールが20個あるのだけど、21番目のボールだけ弾み方が特別だ(しかし弾み方以外は他のボールと何ら変わらない)という場合、最初にballクラスを定義し、それから21個のボールが全部このクラスに所属するように定義します。しかし、21番目のボールは独自のバージョンによってbounceメソッドをオーバーライドします。一方、従来の言語だと、bounceサブルーチンには、変わったボールが跳ねているか、ふさわしく運動しているかどうか確かめるための特別なテストが必要になります。
これは似たり寄ったりに見えるかもしれませんが、特別な場合のコードを特別な場合のオブジェクトを使って分離できるという大きな利点があるのです。ちょうどブロック構造言語がコードをモジュール化するがごとく、オブジェクト指向言語はオブジェクト全体―その状態および行動の双方―をモジュール化します。ほとんどの人はこれによりプログラムの記述がかなり簡潔になることを知っています。なぜなら、修正の必要があるすべてのサブルーチンを捕捉する代わりに一箇所の特別な場合について考えるだけで済むからです。これは特にプログラムのデバッグや手直しをするときに助かります。一つのオブジェクトに付随するすべてのものが一箇所にあるからです。
クラスはそれ自身が他のクラスのメンバーになれるので、この種の特別化は無限に拡大しうることに注意してください。たとえば、rubberBall と billiardBallというクラスを定義したとすると、それぞれがもっと一般的なballというクラスから特徴を継承していると同時に、いくつか独自のものも定義しているわけです。ですから、それぞれのクラスに属する10個のオブジェクトを定義しても、これらのオブジェクトは自分自身で二つの親クラスをオーバーライドする特徴を定義することができます。
オブジェクト指向言語はアドベンチャーゲームの記述に実に有用です。TADSゲームにおいてプレーヤーが命令をタイプすると、システムはあるメッセージをそのオブジェクトまたは関連する複数のオブジェクトに送ります。この点で、プレーヤーコマンドに応じて特定の活動をするオブジェクトのクラスを定義するのは容易です。たとえば、プレーヤーが拾い上げられない(電話ボックスやかなとこのような)オブジェクトは、「take」コマンドに対して簡単な「You can't have that」で応じます。それとは反対に持ち運べるオブジェクトは自らをプレーヤーの持ち物リストに入れます。基本的アドベンチャーファイルのadv.tは基本的なクラスを多数定義していますが、TADSの真の力は独自のクラスを追加できることにあります。
C++やSmalltalkのようなオブジェクト指向の特徴を持つ他の言語の利用者である方は、TADSがオブジェクト指向プログラミングについて少し違った方法を取っていることに気付くと思います。特に、TADSは他の言語と比べてクラスとオブジェクトの区別がかなり希薄です。
C++とSmalltalkでは、クラスはそのクラスのメンバーによって保管されるデータタイプを特定するテンプレートですが、実際にデータの数値を保管するのはオブジェクトだけです(これはCやPascalのような言語における構造体とその構造体のインスタンスの区別に類似している。構造体はデータのレイアウトを定義するが、実際にデータを含むのは構造体のインスタンスのみである)。継承の構造はそのクラスに付随します。あるオブジェクトはある特定のクラスのインスタンスですから、メソッドとデータの「スロット」だけが継承されます―データアイテムの数値がそれ自身によって継承されることはありません。
TADSでは、クラスも一つのオブジェクトですから、クラスとクラスのインスタンスの間に区別がありません。そのために、メソッド同様、データ数値も親クラスから継承することが可能です。TADSにおいて、クラスと普通のオブジェクトの違いは、クラス・オブジェクトの場合、プレーヤーコマンドパーサーに無視されるということだけです。
この方法論の違いがプログラミングスタイルの違いをもたらします。TADSプログラムはほとんどがオブジェクト(クラスのインスタンス)の定義によって構成されます。ゲームプログラムの中ですべてのインスタンスがプロパティーの数値をともなって明確に定義されます。一方、C++やSmalltalkのプログラムは通常、ほとんどクラスを定義していて、インスタンスは実行時に作ります。
物の最も崇高な役割はじっと見つめられることだ。
MIGUEL DE UNAMUNO, Mist (1914)
第1章 | 目次 | 第3章 |