ObjectSquare [1999 年 4 月号]

[新人およびOO初心者に贈る「オブジェクト指向」本格入門]


2.オブジェクト指向コンセプト早わかり

オブジェクト指向は1967年にSimulaというプログラミング言語に対して導入されたのが最初ですが、徐々にユーザーインターフェース設計、OSの構成原理、データベース設計やシステム設計一般、さらには要求分析といったシステム開発の上流工程に対しても適用されるようになってきました。このことは、オブジェクト指向がある工程や分野の特性を反映しているというよりも、問題領域やシステムといった複雑な対象に人間が対処するためにごく自然な一般的視点であり技法である、ということがいえると思います。

状態機械としてのオブジェクト

オブジェクト指向の基本は、内部状態をもつオブジェクトの集団を用いて、それらオブジェクトのイベントのやり取りによって各オブジェクトの内部状態を更新していき、その副作用としてアクションを行うという計算モデルです。いってみれば、イベントをお互いに授受する有限状態機械の集合としてシステムを構成するとき、その各状態機械のことをオブジェクトと呼ぶわけです。

Fig.1
図1:イベントを送受信する状態機械としてのオブジェクト

Fig.2
図2:イベントを送受信するオブジェクトの集合としてのシステム

ですからオブジェクトとは、メモリと外部刺激としてのイベントに反応してどんなアクションを実行するかという規則(メソッドといいます)をもった小人のような存在だとイメージすることができます。メッセージに反応して起動されたメソッドの中でさらに他のオブジェクトにメッセージを送信できます。

インターフェースと情報隠蔽

ソフトウェア工学的に見たときのオブジェクトの特徴は、メッセージ送信という間接的な手段を通してしか内部状態を参照・変更できない情報隠蔽です。受信可能なメッセージのシグニチャ(メッセージ名と各引数および戻り値の型)の集合をそのオブジェクトのもつインターフェースといいます。インターフェースを通してのみオブジェクトの提供する機能を利用できます。逆にインターフェースさえ変えなければ、その状態機械の実現方式はいかようにもできるわけです。この性質を利用して、オブジェクト指向では、他のオブジェクトに影響を与えずにあるオブジェクトの内部のデータ構造やアルゴリズムを変更することが容易にできます。

オブジェクトアイデンティティ

オブジェクトは、お互いのことが識別できなければメッセージを相手に送信することもできないわけですから、オブジェクトは、関数なんかとは違ってもしまったく同じ性質をもっていたとしても1個1個区別できる必要があります。ある人が同じ製品を2回買ったら代金は製品2個分払わなければならないのです。買った製品は1個2個と区別して数えられる必要があります。この性質をオブジェクトはアイデンティティをもつといいます。オブジェクトアイデンティティは、ソフトウェア中ではオブジェクトIDとして自動管理されます。固有名が日常世界では明示的に使われるのに対し、オブジェクトアイデンティティはあくまで同一か否かという「自己同一性」の確認に利用されるだけで、値として意識されることはありません。また、分散環境で複数のメモリ空間を移動するオブジェクトが存在する場合のアイデンティティの管理には工夫が必要になります。

インスタンスとクラス

オブジェクトはその対象を構成する1個1個の具体的な構成要素ですが、よくよく観察すると類似したオブジェクトが複数存在しているのが普通ですし、将来似たオブジェクトを追加する必要が出てくるやもしれません。そこで、個々のオブジェクトではなく、それらの構造や機能の共通性を抽出し型として概念化したもの、一種のテンプレートのことをクラスといいます。

クラスは、共通の属性のセットとそれに関与するメソッドのセットを記述した型です。属性とはオブジェクトの内部状態を特徴づけるパラメータです。それに対し、各属性に具体的な値をデータとして与えたものをインスタンスと呼びます。オブジェクトは何らかのクラスのインスタンスとして生成されます。インスタンスは属性値を保持していますが、メソッドのセットは持たず、自分の属するクラスを参照しているのです。

また、オブジェクト指向でもクラス概念がない、プロトタイプにもとづく言語モデルもあります。新たなオブジェクトはクラスから生成するのでなく、原型オブジェクト(プロトタイプ)からクローニングによってコピーを作り出すのです。そのためあらかじめのクラス定義に縛られることなく実行時にオブジェクトのダイナミックな振る舞いを実現するのに適しています。

汎化と継承

複数の構造の似たオブジェクトをまとめて型として扱う技術がクラスでしたが、型の種類も多くなるとそのままでは管理が大変です。そこで、今度はクラスどうしを型としての類似・差異によって分類してしまおうという発想がでてきます。各クラスの型は属性セットとメソッドセットによって特徴づけれた構造と振る舞いを表現しているわけですから、それらの共通点をスーパークラスとして抽出(汎化)し、差分だけをサブクラスとして別に(特化)してやれば、クラスの分類階層ができあがります。サブクラスに属するオブジェクトはスーパークラスに属すると見なすこともできるという意味で、これをis-a関係と考えることができます。またソフトウェア・モジュールの観点からは、サブクラスからはスーパークラスで既に定義された属性やメソッドを流用できるという意味で、この関係を継承と呼びます。サブクラスではスーパークラスに追加して必要なデータ構造や再定義したい振る舞いのみを記述すればよいわけです。異なる複数のスーパークラスがとれる場合には多重継承と呼ばれます。

クラス分類を行うことで、問題領域やシステムに含まれるオブジェクトを体系的に管理できるようになり、類似性にもとづく理解を促進し、さらにはソフトウェア・モジュールとしての再利用性を高めます。もともと継承は、同一プログラム内でのデータ構造とプログラムコードの流用を目的として考案されたものです。したがって、単にプログラムの流用率を最大化するという近視眼的な発想にもとづけば必ずしもis-a関係にならないクラス間の継承でもたまたま使えるデータ構造やメソッドがあればOKということになってしまいます。しかし、システムやプログラムの複雑さに対処するという大局的な観点からはこのようなアドホックな継承は望ましくありません。is-a関係にもとづくクラス分類という観点から継承を利用すべきです。その際の指針は、外部観測できる振る舞いにおいて下位クラスのインスタンスが上位クラスのインスタンスとみなすことができるかというLiskovの置換原理です。特に多重継承にもとづく設計は振る舞いの正確な予測がむずかしくなりがちで、後で触れるデザインパターンの観点からも継承の代わりにオブジェクト間でのメッセージ転送を重視した委譲にもとづく設計が推奨されます。

ポリモーフィズム

オブジェクトどうしの相互作用はメッセージの送受信にもとづいています。メッセージの選び方で相手にどんな仕事をしてもらうかが決まるわけです。しかし、実際には、メッセージを具体的なアクションに対応させる最終的決定権をもっているのは受信側のオブジェクトです。同じmove()というメッセージであっても、その実際上の効果は受信側のオブジェクトのもつメソッドの内容によって異なります。航空機オブジェクトであれば飛行するでしょうし、イルカオブジェクトであれば泳ぐことでしょう。メッセージを媒介することによって、送信側の意図と受信側のアクション(メソッド起動)の対応の自由度が得られるわけです。これをメッセージのポリモーフィズムといいます。従来の手続き呼び出しであれば、イルカ用の移動手続き呼び出しというように送信側で詳細を決めなければならなかったわけです。

ポリモーフィズムとは、先に情報隠蔽のところで説明した外部インターフェースと内部実装の対応を受信オブジェクト側に任せるための機構だと考えることができます。これによって、新たなクラスが追加されても反応できるメッセージさえ共通に定義しておけば、それを呼び出して使うクライアント側のプログラムはいっさい影響を受けずに済むことになります。

集約と複合オブジェクト

オブジェクトは通常複数で協調して働きますが、その協調の様子が非常に密接である場合、それらをまとめて1つのオブジェクトと見なす方が便利な場合があります。そうした名目で作り出したオブジェクトを集約といったり複合オブジェクトといったりします。ですから複合オブジェクトとその要素オブジェクトとの間には全体-部分の関係が成り立ちます。デザインパターンでもCompositeとして再帰的な複合オブジェクトの合成パターンが定式化されています。また、継承の替わりに委譲によって、機能をダイナミックに追加したり交換したりするのも、この複合オブジェクトの構成原理の応用です。

全体オブジェクトのとる属性は部分オブジェクトにも継承されるのが普通です。たとえば、自動車オブジェクトが速度100km/sであれば、その乗客の移動速度も100km/sです。さらに部分が全体に存在依存する場合をコンポジット集約と呼びます。部品が他の全体オブジェクトに共有されることはなく、特定の全体オブジェクトに固有の存在として一体化されていることを示します。集約のセマンティクスにはさまざまなものがあり、それを精密に定義しコンポーネントウェア等オブジェクト部品の組み立て技術に応用するのは今後の研究課題です。


© 1999 OGIS-RI Co., Ltd.

Prev.

Index

Next