Last update 1999/08/07

オブジェクト指向と時間・空間

(C)平山直之
無断転載は禁止、リンクはフリー
誤字脱字の指摘は歓迎


時間は有限か?

かつて哲学においてよく議論の対象とされた問題に、

「時間は有限か?」

というものがあります。この命題に対するカントの答えは明快で、

「有限とか無限とかいうものではない」

というものです。

同じようによく質問された問題に、

「空間は有限か?」

というものがあります。この命題に対してもカントは明確に答えます。

「有限とか無限とかいうものではない」

と。

それは詭弁ですか?

カントの答えは果たして詭弁なのでしょうか。もちろんそうではありません。

彼の答えを理解するには、まず質問の意味を正しく理解しなければなりません。そして、われわれが命題に対してしばしば抱く偏見を取り除かなければなりません。

その偏見とは、いったい何なのでしょうか。

それは、われわれが命題が正しいと思い込んでしまうこと、言い換えると命題に論理的な整合性があると信じ込んでしまうこと、です。命題=前提と考えてしまうことが間違いの始まりなのです。

「時間は有限か?」という質問が正しくない(=論理に整合性がない)とする理由を、カントは、「この文脈上では有限・無限とはモノ自体の内在的な属性ではなく、時間軸の中にあって初めて成り立つこと」だからとしています。空間においても同様に、「この文脈上では有限・無限とはモノ自体の内在的な属性ではなく、空間の中にあって初めて成り立つこと」だからです。つまり、時間そのものは時間軸の中になく空間そのものは空間の中にないのだから、それ自体には有限とか無限とかはなり立たないのです。

C++で言えばこういう感じです。

struct Time {
    bool inifinity;
};
struct TimeSpace {
    std::list<std::pair<Period*,Object*> > objects;
};

struct Period {
    bool infinity;
};

struct Object {
};
これは間違い こっちが正しい

ですから、論理の範囲内で語る限り、正しい答えは、カントの言うとおり「回答不能」です。

これらのことを、もっと一般化して語ることができます。すなわち、論理とは前提があって初めて成り立つということです。

論理は白黒を絶対につけるものではありません。論理を極めると、ある前提の範囲内では証明が不可能なことが証明されることが往々にしてあるのです。論理とは前提があって初めて成り立つものだからです。このことをゆめゆめ忘れてはいけません。

オブジェクト指向と前提

論理の構築には、前提が必要不可欠です。

だからといって、このことがオブジェクト指向設計に対していったいどのような影響を与えるのでしょう。

かなり唐突ですが、ここでアクションゲームのオブジェクトについて考えてみましょう。アクションゲームのオブジェクトをあらわすクラスをC++で作れ、と指示されたら、あなたはいったいどんなクラスを定義するでしょうか。

あまりにも具体性のない指示ではありますが、これ以上の指示がなければ、私なら訝りながらもこんな感じにするでしょうか。

class Object {
public:
    Object(void){}

    virtual void Process(void){}
    virtual void DrawTo(Screen*){}
    virtual bool HitTest(HitRect*){}

private:
    int X;
    int Y;
    HitRect* Hit;
};

2Dシューティングゲームなどのアクションゲームだったら、これでOKでしょう。でもツール類やRPG・シミュレーションなんかを作るときは、これではまずいことがしばしばあるのです。

いったいなぜなのでしょうか。

主観・客観と前提

近代の哲学者は、この世に客観が存在しないことを見抜きました。正確に言うと、「客観は存在するかもしれないが、証明し得ない(ので人間にとっては存在しないのと同じ)」ということです。

私は私の周囲に起こる現実的な事件を、すべて客観だと思っています。しかし、あなたが思う客観とは違うでしょう。私とあなたが違う場所に立っている時点で、同じ物が同じ角度で見えているはずがないからです。「見える」という表現を使うと視覚的なものについてのみ語っているように思われるかもしれませんが、抽象化しても同じことが言えることはすぐにわかると思います。別の人間がまったく同じコンテキストでモノを考えることはありません。

コンピュータ的に言えば、私とあなたで同じメモリ内容と同じレジスタ内容と同じストレージ内容と同じ処理能力を持っている、ということは決してありません。より正確に言えば、シュレーディンガーの猫と同じ理由で証明し得ないのです。証明しようとするとレジスタ変わっちゃうのです。

そして、どんな方法で証明しようとも、その証明方法は何かの前提(たとえば科学)があって初めて成り立つものです。その前提を明らかにしようとする行為は徒労でしかありません。苦労して見つけ出した前提はまたその前提が成り立つ前提(例えば論理そのもの)を必要とし、そしてその行為はただ堂々巡りを続けるだけだからです。中世の哲学者は、この堂々巡りの最果てこそ「一なる根拠=神」であると考えました。しかし「神」はもういません。

結局、モデリングしようとしている対象が現実に近ければ近いほど(シミュレーション度が高ければ高いほど)、この「この世には客観が存在しない」という現実が高い壁となって立ちはだかるようになります。抽象度の高い空間ではあなたが神を作る余地が残されていますが、具体性を帯びれば帯びるほどその領域は侵されていくからです。

ゲームプログラミングで言えば、場面が変わったときのパラメータ類の連続性が高いRPGやシミュレーションではよくあることでしょう。一つのオブジェクトが複数の役割を持ち、一つのオブジェクトを複数の角度から見ることになるからです。

これを上のクラスに当てはめてみましょう。

たとえば、上のクラスでは、X座標・Y座標を内部に持っています。しかし、座標というものは、よく観察してみると、本来それ自身の属性ではないはずなのです。なぜなら、座標とはそれが拠って立つ座標系の中においてのみ成り立つものだからです。

そして、構築しようとしているシミュレーションが高度であれば高度であるほど、オブジェクトを取り囲む座標系は多くなります。1次元の座標系だってあります。「リストにおける順番」だって「座標系の中の座標」が1次元になっただけのものなのですから。

オブジェクト指向の入門書なんかでも、上のようなクラスはよく現れます。たとえば、「住所」属性を持つ「人間」クラスなどで。しかし、よく考えれば分かるように、それは「住所録」という文脈(=前提)で「人間」を記述しているからこそ許されることであって、「住所」などは「人間」の持つ普遍的な属性ではないのです。これを無批判に受け入れると、手痛い被害を被ることになります。

主観・客観システムを導入したオブジェクト指向言語というものを、私は寡聞にして知りませんが、これをなんとかオブジェクト指向分析に当てはめるなら、「主観」という「関係」オブジェクトを間に挟むのが一般的でしょう。

つまりModel-Viewです。Modelとユーザの間にはViewが入るのです。ユーザは、主観のメタファであるところのViewを見ることはできますが、客観のメタファであるところのModelを直接見ることはできないのです。

でもね……

それでもやはり、2Dのシューティングをその場限りに作る(より現実度の高い状況で再利用しない)なら、やっぱり上のような設計でよいのです。

2Dシューティングであれば上のクラスでよいのは、2Dシューティングでは一般的にモノの見え方は一つであり、スクリーンの持つ座標系は絶対で、その座標を管理することがオブジェクト指向を導入するそもそもの目的であって、座標類を取り除いてしまったら、オブジェクトの属性などなにも残らないからです。そうした前提が成り立つ限り、上のクラスのような設計は決して悪い設計ではありません。Objectクラスは、戦闘機や弾ではなく、「座標とスプライトの複合体」という抽象的な構造をあらわしているからです。

もちろん、そのことをわかってなかったり忘れたりすると、痛い目をみることもあるでしょう。それが恐かったらクラスを分けるのも一つの手です。でも、無駄にやりすぎると不必要に複雑なものになって、現実が複雑だからモデリングしていることや、データの管理がめんどくせえからオブジェクト指向を導入しているのを忘れてしまったりしかねません。

クラスを設計するときには、自分がどんな文脈でモノを記述しようとしているのかを決して見失わないようにしましょう。クラス設計で一番大事なのは、クラスの属性を考えることではなく、クラスが成り立っている前提を見抜くことなのです。そしてその前提を見抜くことができれば、自分の作っているクラスがどのレベルで再利用できるかも自ずと分かるでしょう。

これを読んでみて面白かったという人は、このページに行ってみましょう。


(C) 1998 Naoyuki Hirayama. All rights reserved.