オブジェクト指向プログラミング

互いに密接な関連性を持つデータとメソッドをひとつにまとめてオブジェクトとして用いるソフトウェア開発手法

オブジェクト指向プログラミング(オブジェクトしこうプログラミング、: object-oriented programming、略語:OOP)とはプログラミング技法の一つであり、任意の関連性を持つデータ変数またはプロパティ)とコード関数またはメソッド)をひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定義と、それらオブジェクトを相互作用させる様々なプロセスの設定を通して、コンピュータプログラムを構築することを主眼にしている。

オブジェクト指向という言葉自体は、計算機科学者アラン・ケイによって作り出されている。Simula言語などにインスパイアされたケイが1967年頃に口にしたと伝えられるこの造語は[1]、彼が1972年から開発を始めた言語Smalltalkの設計を説明する過程で明確な用語として発信され、1981年頃から知名度を得るようになった。80年代半ばになるとオブジェクト指向の解釈は、元々のアラン・ケイによるSmalltalkの様式と、1983年に計算機科学者ビャーネ・ストロヴストルップが公開したC++の様式に二分された。前者ではメッセージングという概念が基礎にされ、後者ではSimula67由来の諸機能を加えた抽象データ型のスーパーセットが基礎にされていた。現在では、C++とそのモデルになったSimula67の様式がオブジェクト指向の標準になっている。

特徴編集

OOPではクラスベースと呼ばれるスタイルが標準にされている。他にプロトタイプベースと呼ばれる後発のスタイルもあるが、こちらは少数派である。クラスベースのOOP言語は、Smalltalkの様式とC++の様式で二分されており、C++の方がずっと多数派である。C++の様式は、静的型付け動的型付けの分類で大別されている。それらの主な特徴を箇条書きするとこうなる。

本稿では最も標準的なクラスベースのC++様式の静的型付けを基準にして説明する。

クラスとインスタンス編集

OOPの要点であるクラスは、データ構造とそれを扱うための操作・振る舞いをひとまとめにした一種のモジュール機能として定義されており、その実装はSimula67由来の継承と動的ディスパッチを加えた抽象データ型のスーパーセットにされていることが多い。OOPを理解する上でクラスと、非OOP言語でのモジュールの違いを知ることは重要である。どちらも手続きデータの複合体であるが、OOPのクラスにはモジュールの抽象化(abstraction)を促進させるカプセル化継承ポリモーフィズムをサポートする機能が導入されており、プログラムの再利用性と保守性を高める上でより有用になっている。

クラスのデータ構造はレコード型構造体に似た書式で定義されることが多く、データ構造の要素は言語ごとにフィールドプロパティ属性、メンバ変数などと呼ばれている。クラスに定義される操作・振る舞いはメソッドやメンバ関数などと呼ばれる。メソッドは特定の対象に所属させることを前提にしたアドホック多相英語版付きの関数/手続きである。ここでのアドホック多相はメソッド内で扱われている特定変数の束縛先対象を切り替えるための機能になり、後述のthis参照などが該当している。

C++様式のクラスベースはオブジェクトを、型理論に沿った(type)と型付け値(term)に分離している。その型の一種であるユーザー定義型(user defined type)がクラスにされており、その型付け値がインスタンスになっている。ユーザー定義型とは構造体と同じものであり、OOPでは手続き(のポインタ)も構造体メンバにされている。ユーザー定義型はオブジェクト型とも呼ばれるが、このオブジェクト型と後節の「オブジェクト」の意味上の繋がりはない。クラスはインスタンスのひな型であり、インスタンスはクラスを実体化したものである。実体化=インスタンス化とは対象クラスの全変数内容を決定し、ヒープ領域の基底アドレス(this)を定めた上でそこにメモリ展開するという作業を指している。コンパイル時にその構成が確定されるユーザー定義型は静的型付けであり、実行時にもその構成を変更できるユーザー定義型は動的型付けである。

オブジェクトとは編集

クラスベース言語での「オブジェクト」は、一般的にはインスタンスを指す用語として説明されているが、このような重複語になった背景にはOOPの原点であるSmalltalkからの事情がある。Smalltalkは、全てのプログラム要素はオブジェクトであり、全てのオブジェクトはクラスのインスタンス化であり、クラスもまたオブジェクトであると定義していた。そこではクラスもまたメタクラス(型)のインスタンス化(型付け値)になり、そのメタクラスもまた他のメタクラスのインスタンス化になっていたので、クラスインスタンスは即ちオブジェクトの性質(相対性)を指すための言葉になっていた。これがC++様式では簡素化されて、クラスとインスタンスは型付け値の役割に固定され、メタクラスはクラス構成の動的変更機能に固定されたので、上述のインスタンス化の相互再帰が失われたオブジェクトは、インスタンスと同じ意味の言葉として残されることになった。またSmalltalkは、オブジェクトは他のオブジェクトと相互作用(interaction)するとも定義しており、この相互作用とは各種演算と同義である。Smalltalkのクラスは型付け値でもあるのでオブジェクトであるが、C++様式のクラスはただの型なので演算対象に出来ないことからオブジェクトではなくなっている。

Smalltalk方言のSelfを原点とするプロトタイプベースは、オブジェクトからクラスとインスタンスの相対性を無くしたスタイルである。数値・文字列・シンボル・配列・関数・構造体(オブジェクト型)といった基本的な型は備えられているが、これはオブジェクト種類の区別に特化されたものなので、型理論に沿ったクラスベースのそれとは厳密には異なっている。プロトタイプベースのオブジェクトは、Smalltalkと同じ意味のままである。オブジェクトの表現はスロット(シンボルとコンテンツのペアデータ)の可変長配列でなされており、オブジェクトの識別は専らダックタイピングによってなされる。クラス概念が無いのでサブクラス化(継承)とインスタンス化は成立せず、代わりにクローン(複製)によってオブジェクトの派生化と実値化がなされている。複製元オブジェクトは、複製先オブジェクトのプロトタイプと呼ばれる。

オブジェクト指向の三大要素編集

クラスベースOOPは上述のクラス機能を中心にしており、そのクラス機能の実装様式を規定している以下の三項目は、日本では三大要素または三大原則などと呼ばれている。非OOP言語のプログラムモジュールに三大要素仕様を加えたものがOOP言語のクラスになるが、各要素の軽視重視と導入方式には言語ごとに様々な違いがある。カプセル化はthis参照の機構とデータ/メソッドの可視性を指定できる機能、継承は自身のスーパークラスを指定できる機能、ポリモーフィズムはオーバーライド仮想関数テーブルを処理できる機能とされていることが多い。[独自研究?]

カプセル化編集

データ構造とそれを扱うためのメソッド群を情報隠蔽の概念と合わせてモジュール化(パッケージ化)するという手法がカプセル化と呼ばれる。カプセル化されたメソッドは、this値が暗黙の先頭引数として常に渡されるように実装される。this値とはクラスのデータ構造をメモリ展開するためのヒープ領域の基底アドレスを指しており、インスタンス化時に確定されたthis値によってメソッドは専用のデータ構造にアクセスできる。専用メソッドを通してのデータ構造の閲覧と変更は、抽象データ型の考え方に沿ったデータ構造の抽象化を意味することになり、これはデータ抽象英語版と呼ばれる。データ閲覧用メソッドはゲッター/アクセッサと呼ばれ、データ変更用メソッドはセッター/ミューテイタと呼ばれる。

情報隠蔽英語版はそのクラスのデータ構造の各要素および各メソッドを必要に応じて内部隠蔽する仕組みである。内部隠蔽されたデータ要素とメソッドはそのクラス外部からのアクセスが禁止される。抽象データ型本来の形式ではデータ構造のみが隠蔽対象になるので、これはデータ隠蔽とも呼ばれる。隠蔽指定外のデータ要素とメソッドは外部公開されて、そのクラス外部からもアクセス可能になる。外部公開の範囲を指定する機能はアクセスコントロールと呼ばれており、クラスのレキシカルスコープを基準にした段階的なアクセス許可範囲は可視性と呼ばれる。可視性は無制限・任意クラスグループ限定・派生クラスグループ限定・自クラス限定の四段階がUMLでは標準にされている。

継承編集

既存クラスのデータ/メソッド構成に、任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義するという手法が継承と呼ばれる。また、各クラスの共通構成部分を括りだして特有構成部分と分離することでオブジェクトを体系化し、加えて重複記述の削減をもたらす機能と解釈されることもある。これは差分プログラミング目的の継承と言われるが、2000年代になるとSOLID原則の重視に伴なって、既存構成に抽象メソッドを置いて新規構成にその実体メソッドを置くというメソッドオーバーライド目的の継承の方が要点にされるようになっている。データ/メソッドの新規構成ではなく、メソッドの実装内容を付け足していくための継承である。そこでは特にデータ構造を付け足しての階層的なデータの分散配置は倦厭されるようになっている。

既存クラスは基底クラス、親クラス、スーパークラスなどと呼ばれ、新しいクラスは派生クラス、子クラス、サブクラスなどと呼ばれる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。抽象メソッドを持つクラスは抽象クラスと呼ばれる。抽象メソッドのみで構成される純粋抽象クラスの継承は、インターフェースの実装(実装継承)と呼ばれて振る舞い抽象目的の継承になる。返り値の型と引数リストのみが定義されて実行コードブロックが未定義のままの抽象メソッドは、派生クラス側の実体メソッドでオーバーライドされる。

ポリモーフィズム編集

異なる種類のクラスに共通の操作インターフェースを持たせてオブジェクトの振る舞いを抽象化するという手法がポリモーフィズム(多態性)と呼ばれる。OOPで語られる多態性は多くの場合、継承構造を利用したサブタイプ多相英語版を対象にしているが、関数型スタイルではアドホック多相英語版が用いられ、コンポジションではパラメトリック多相英語版が用いられる。設計としてはコンパイル時に確定されたメソッド名から呼び出されるプロセス内容が実行時に決定されるという仕組みを指しており、一つのメソッド名からその実行時状態に合わせた個別のメソッド処理が呼び出されるようにするという演繹的意味と、各クラスの同種機能メソッドを一つの共通メソッドにまとめて実行時状態に合わせたメソッド処理が呼び出されるようにするという帰納的意味がある。

その実装としてはメソッドオーバーライド機能を活用した仮想関数と、実行時パターンマッチング機能を活用した総称関数の二つが挙げられる。前者は標準的なクラスベース向けであり、後者は関数型スタイル向けである。仮想関数英語版はスーパークラスの抽象メソッドの呼び出しを、それをオーバーライドしたサブクラスの実体メソッドの呼び出しにつなげるという動的ディスパッチ機能である。総称関数英語版はオブジェクトの実行時パターンマッチングを使用する独立関数であり、その引数にされた各オブジェクトの型(=クラス)の組み合わせに従って実行コードブロックを選択決定するという多重ディスパッチ機能である。

コンポジションとデリゲーション編集

コンポジション(合成)とデリゲーション(委譲)は継承を帰納的に分解した仕組みと言えるものであり、または合成と委譲による連携を演繹的に最適化した仕組みが継承であるとも言える。OOPにおける合成と委譲は、SmalltalkSimula67由来の継承機能をオブジェクトの再帰構成という観点から再解釈したものがデザイン上のルーツになっている。継承はIs-aの委譲、合成はHas-aの委譲と読み替えることができる。

合成とは、クラスに特定処理の委譲先になる部品クラスを1個以上持たせた構造であり、クラスがとある処理を要求されてそれに対応できるデータ/メソッドを持っていない場合は、それに対応できる部品クラスを選択して処理を委譲するという仕組みである。その要求判別と選択過程を自動化したものが継承であり、部品クラスを基底クラスに置き換えて暗黙の委譲先にしたものである。継承がもたらしたデータ/メソッド検索の自動化は特にコーディング負荷を軽減した。しかしその暗黙委譲は実際に参照されるデータ/メソッドの把握を困難にし、リスコフの置換原則違反を招きやすいという欠点も明らかになったので、合成との使い分けが重視されるようになった。SOLID原則の重視に伴ない、既存構成に新規構成を付け足していくという差分プログラミング目的および共通構成を括りだして特有構成と分離していくという同様の目的では、継承よりも合成を用いる方がよいと考えられている。

コンポジション英語版の一種であるアグリゲーション(集約)とコンテインメント(包含)は、同種要素集合を保有するコンテナ(List/Set/Map)を表現する。様々なデータ型の要素を取り扱える汎用コンテナクラスを表現するための差分プログラミング手法がジェネリクスである。ジェネリクスはコンポジションと密接に関連したパラメトリック多相英語版としてOOP初期から重視されている。

動的ディスパッチとメッセージパッシング編集

動的ディスパッチ英語版ポリモーフィズムの原型的仕組みであり、例えば継承構造上でのthisによるシングルディスパッチを最適化した機能が仮想関数になっている。動的ディスパッチは、コンパイル時に確定されたメソッド名から呼び出されるメソッド内容(実行コードブロック)が実行時に決定される仕組み全般を指している総称用語である。メソッドに与えられた各引数の型の組み合わせに従って、実行コードブロックが選択分岐される仕組みのシングルディスパッチと多重ディスパッチを包括している。先頭引数の型パターンマッチング固定で実行コードブロックが選択決定(ディスパッチ)されるのはシングルになり、そうでないならば多重になる。

メッセージパッシングでは前述の引数の型だけでなく、メソッド名も実行時に解釈される要素にされており、そこでただのシンボルとして扱われるメソッド名はセレクタと呼ばれている。セレクタはメッセージ式を基本文とするSmalltalk様式のOOPで用いられる。object selector: paramような書式でオブジェクトの共通窓口となるメッセージレシーバーに、セレクタと引数値で構成されたメッセージが送られる。また、object.call(method_name, param)のような書式でオブジェクトの共通窓口関数をコールするのもメッセージパッシングと呼ばれる。これは遠隔手続き呼出しオブジェクト要求ブローカーで用いられており、分散オブジェクトの標準的なインターフェース機構になっている。メソッド名(関数名)も実行時に解釈されるという特徴を指してメッセージパッシングと呼ぶ。メッセージレシーバー内では、渡されたセレクタの文字列照合の条件分岐によって実行コードブロックが選択されることが多く、OOP原点のSmalltalkは、引数とthisが与えられるその実行コードブロックをメソッドと呼んでいた。

インターフェース編集

インターフェースカプセル化を更に突き詰めた仕組みであり、データ抽象とメソッド抽象と情報隠蔽を合わせて実現する最もOOPらしい機能と言える[独自研究?]。OOPで言われるインターフェースは、抽象メソッドで構成される一種の抽象型と定義されている。ソフトウェアコンポーネント間の相互通信媒体として用いられることが多く、SOLID原則の重視に伴ないクラス間の結合にも多用される。各言語での導入様式としては、抽象メソッドのみからなる純粋抽象クラスが基本形にされている。抽象のままなのでインスタンス化はできない継承専用クラスになる。インターフェースの抽象メソッドのメソッド内容(実行コードブロック)は、それを実装したクラスの同名メソッドで記述されることになる。インターフェースはクラスの振る舞いを投影した抽象体であり、ゲッター/セッター/プロセスになる各抽象メソッドの実装内容は、利用者側から隠されて実行時のその都度に決定されることになる。

多重ディスパッチとミックスインとトレイト編集

多重ディスパッチは振る舞い(behavior)を中心にしてオブジェクトを扱うための手法であり、これを重視したOOPでのオブジェクトは、振る舞いサブタイピングが省かれたデータクラスに特化されることになる。そこでは多重ディスパッチ用の独立関数がメソッドと呼ばれるが、正確にはディスパッチ先になる個々の実行コードブロックがメソッドであり、その多重定義で総称メソッド(総称関数)と呼ばれる。総称メソッドは1個以上のインスタンスを引数にし、その各引数インスタンスの型(=クラス)の組み合わせに従って、実行コードブロックを選択決定(ディスパッチ)する。その選択分岐にはインスタンスのパターンマッチングが用いられ、インスタンスの型のほか、その型に付加されている文脈(context)による判別の方が重視されている。この文脈は実体の無いただのシンボルであり、マーカーインターフェースによるアドホック多相と同義である。この1個以上の文脈をクラスに継承させることを指して、多重ディスパッチ用法上のミックスインと言われる。多重ディスパッチは関数型寄りのポリモーフィズム様式と言えるものである。

多重ディスパッチの流れを汲むトレイトは、振る舞いを主体にした継承専用クラスであり、その継承先クラスに結び付けるための独立関数集合=メソッドモジュールと考えてもよい。インターフェースサブタイプ多相英語版であるのに対して、トレイトは概念上はアドホック多相英語版でクラスとメソッドモジュールを結び付ける仕組みである。インターフェースではメソッド定義のみがなされてその実装先クラス内でメソッド実装がなされるのに対し、トレイトではメソッド定義とメソッド実装の双方をその継承先クラスから独立して行えるが、継承先クラス内で任意メソッドをオーバーライド実装することもできるのでインターフェースと似通ったものにもなる。トレイトは概念上はアドホック多相なので、クラスからメソッドモジュールへのthisなどの型情報の引き継ぎは言語別の特定仕様になり、暗黙と明記を含めた関連型(associated type)などが用いられる。関連型はパラメトリック多相英語版であり、オブジェクトの型だけを要素として扱うコンポジションと解釈される。なお、トレイトのアドホック多相は、型理論の型構築子によるラッピングと解釈した方が自然とされている。この1個以上のトレイトをクラスに継承させることを指して、トレイト用法上のミックスインと言われる。トレイトは関数型寄りの継承様式と言えるものである。

歴史編集

1954年に初の高水準言語FORTRANが登場すると、開発効率の劇的な向上と共にソフトウェア要求度も自然と高まりを見せてプログラム規模の急速な拡大が始まった。それに対応するために肥大化したメインルーチンをサブルーチンに分割する手法と、スパゲティ化したgoto命令制御フロー構文に置き換える手法が編み出され、これらは1960年に公開された言語「ALGOL60」で形式化された。当時のALGOLはアルゴリズム記述の一つの模範形と見なされたが、それと並行して北欧を中心にした計算機科学者たちはより大局的な観点によるプログラム開発技法の研究を進めていた。

Simulaの開発(1962 - 72)編集

1962年、ノルウェー計算センターでモンテカルロ法シミュレーションを運用していた計算機科学者クリステン・ニゴールは、ALGOL60を土台にしてProcessと呼ばれるコルーチン機構を加えたプログラミング言語「Simula」を制作し、続けてその拡張にも取り組んだ。ニゴールの同僚で、1963年にSimulaを汎用機UNIVAC系統上で運用できるように実装した計算機科学者オルヨハン・ダールは、Processにローカル変数構造を共有する手続き(サブルーチン)を加えてパッケージ化する言語仕様を考案し、これは任意の変数と手続きをまとめるプログラムモジュールと同類の機能になった。程なくしてALGOL60コンパイラに準拠していての限界を悟ったニゴールとダールは、1965年からSimulaを一から再設計するように方針転換した。その過程で彼らは、計算機科学者アントニー・ホーアが考案して1962年のSIMSCRIPT(FORTRAN用のスクリプト)に実装していたRecord Classを参考にしている。Record Classはソースコード水準の抽象記号を、各汎用機に準拠したマシンコード水準の実装符号に落とし込む段階的データ構造のプログラム概念であった。これをモデルにした継承と、その継承構造を利用した仮想手続き(仮想関数)の仕組みも考案され、上述のパッケージ化されたProcess(モジュール)に継承と仮想手続きの両機能を加えたものを「クラス」と定義し、クラスをメモリに展開したものを「オブジェクト」と定義する言語仕様がまとまり、1967年に「Simula67」が初公開された。オブジェクトという用語は、MITの計算機科学者アイバン・サザランドが1963年に開発したSketchpadの設計上にあったObjectが先例であった。SketchpadCADGUIの原点として知られており、後述のSmalltalkのモチーフの一つにもなっている。Simula67コンパイラはまず汎用機UNIVAC上で運用され、翌年から汎用機バロースB5500などでも稼働されて北欧、ドイツ、ソ連の各研究機関へと広まり、1972年にはIBM汎用機System/360などにも導入されて北米全土にも広まった。その主な用途は離散事象および物理シミュレーションであった。

構造化プログラミングの提唱(1969 - 75)編集

1960年代半ばになるとプログラム規模の際限なき拡大に伴なうソフトウェア開発の難航が頻発するようになり、いわゆるソフトウェア危機問題が取り沙汰されるようになった。その解決に取り組んだ計算機科学者エドガー・ダイクストラは、1969年のNATOソフトウェア工学会議で「構造化プログラミング」という論文を発表しトップダウン設計、段階的な抽象化、階層的なモジュール化、共同詳細化(抽象データ構造と抽象ステートメントを連携させて具象化する概念)といった技法を提唱した。その論旨はプログラム正当性検証技術の確立であり、数学証明に倣った視点でソースコードを適切に分割して抽象化することが勧められていた。しかしこの構造化プログラミングは後に曲解されて、制御フロー構文(順次・分岐・反復)を勧める論旨で世間に広まることになり、ダイクストラ本来の論旨であったプログラムモジュールを抽象体として扱おうとする考え方は当時の世間には伝わらなかった。共同詳細化は抽象データ構造を専用ステートメントを通して扱おうとする概念であり、Simula67の手続きを通してクラス内の変数にアクセスする仕組みに似ていた。段階的な抽象化と階層的なモジュール化は、SIMSCRIPTの段階的データ構造とSimura67の継承による階層的クラス構造が先例になっていた。ダイクストラホーアダールの三者は1972年に『構造化プログラミング』と題した共著を上梓しており、その階層的プログラム構造という章の中でダールは、Simulaの設計理念を更に明らかにした。

1970年に公開されたALGOL68拡張版は、任意のサブルーチンとデータをまとめるためのプログラムモジュール機能を初めて形式化した。1974年にMITの計算機科学者バーバラ・リスコフは「抽象データ型」を提唱し、前述のモジュールの共同詳細化をその振る舞いによって意味内容が決定される抽象データという考え方でより明解に形式化した。1975年に計算機科学者ニクラウス・ヴィルトは、モジュール機能を眼目にした言語Modulaを提示してモジュラープログラミングというパラダイムを明確にしている。また、1970年代後半からIBM社を中心にした研究者たちが(エドワード・ヨードンなど)サブルーチンモジュールとデータ構造を連携させる構造化設計および構造化分析と総称される技法を発表し、この構造化開発は1980年代までのソフトウェア開発の主流になっている。モジュール凝集度結合度は構造化開発由来である。このようにいささか奇妙ではあるが、Simulaのクラスとオブジェクトというプログラム概念は、プログラムモジュールの登場から構造化分析設計技法へといった進化の流れとは関係なく、しかもその前段階において生まれていた。

Smalltalkとオブジェクト指向の誕生(1972 - 81)編集

Simula発のProcessとクラスの示した可能性は、パロアルト研究所の計算機科学者アラン・ケイによる「メッセージング」という考え方のヒントになった。ケイはプログラム内のあらゆる要素をオブジェクトとして扱い、オブジェクトはメッセージの送受信でコミュニケーションするという独特のプログラム理論を提唱した。それには従来の関数呼び出しをセレクタの実行時解釈に置き換えて積極的な委譲を推進するメッセージ式と、プログラムコードとしても解釈できるデータ列を送信してそれを任意のタイミングで評価(eval)することで新たなデータを導出できるなどのアイディアが盛り込まれていた。これらの遅延結合パラダイムは非同期通信や単方向通信への可能性をも開いており、この発想の背景にはLISPの影響があった。メッセージを駆使するオブジェクトの構築には、Simula発のそれにプラトンイデア論を重ね合わせたクラスインスタンスの仕組みが導入された。オブジェクトとメッセージングの構想に基づいて開発された「Smalltalk」はプログラミング言語とGUIフレームワークを併せたものとなり、1972年にデータゼネラルNova上での1000行程度のBASICを使った試作(概念実証)を経て、翌1973年に新開発されたゼロックスAlto上で本格稼働された。Smalltalkの設計を説明するためにケイが考案した「オブジェクト指向」という用語はここで初めて発信された。またケイのメッセージング構想はMITの計算機科学者カール・ヒューイットに能動的なプロセス代数を意識させて[2]、1973年発表のアクターモデルのヒントにもなっている。しかし委譲の多用とデータ列が常にコード候補としても扱われる処理系は、当時のコンピュータには負荷が大きく実用的な速度を得られないという問題にすぐ直面した。Smalltalk-74(新たに開発されたBitBLTを使った高速描画版Smalltalk-72)からSmalltalk-76の過程で、やむなくメッセージは(多くの場合)関数の動的コールに、メソッドはパターンマッチ処理から単なる関数へ置き換えられるなど構想時の柔軟さが失われるほど最適化された。また、ケイの留保した継承機構[3]も導入されてオブジェクトは抽象データ型の性格も有するようになった。

1980年のSmalltalk-80は、元々はメッセージを重視していたケイを自嘲させるほど同期的で双方向的で手続き的なオブジェクト指向へと変貌していた。それでも動的ディスパッチと委譲でオブジェクトを連携させるスタイルは画期的であり、1994年に発表されるデザインパターンの模範にもされている。1981年に当時の著名なマイコン専門誌『BYTE』が、Smalltalkとその理念であるオブジェクト指向を紹介して世間の注目を集める契機になったが、ケイの思惑に反して技術的関心を集めたのはクラスの仕組みの方であった。オブジェクト指向は知名度を得るのと同時に、Simula発のクラス継承と動的ディスパッチ)および抽象データ型(データ抽象とデータ隠蔽)にマウントされて解釈されるようになり、それらのコンセプトがケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。

C++の開発と普及(1979 - 88)編集

Simulaを研究対象にしていたAT&Tベル研究所の計算機科学者ビャーネ・ストロヴストルップは、1979年からクラス付きC言語の制作に取り組み、1983年に「C++」を公開した。C++で実装されたクラスは、Simula譲りの継承と仮想関数に加えて、レキシカルスコープの概念をクラス構造に応用したアクセスコントロールを備えていた。C++で確立されたアクセスコントロールはカプセル化の元になったがコードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(not just)オブジェクト指向言語であると明言している。1986年にソフトウェア技術者バートランド・メイヤーが制作した「Eiffel」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性/手続き/関数の三種構成で、手続きで属性を変更して関数で属性を閲覧するという形式に限定されており、これは抽象データ型に忠実な実装であった。アクセスコントロールはモジュラープログラミングの情報隠蔽に沿った方式になり、仮想関数機能は延期手続き/関数として実装された。

1986年からACMOOPSLAを年度開催するようになり、オブジェクト指向は従来の構造化開発に代わる技術として明確に意識され始めた。OOPSLAのプログラミング言語セクションでは、抽象データ型を基礎にしたクラス・パラダイムが主要テーマにされ、それを標準化するための数々のトピックが議題に上げられている。モジュール分割抽象化再利用性階層構造、複合構成、情報隠蔽、実行時多態、動的束縛総称型永続性並行性自動メモリ管理といったものがそうであり、参画した識者たちによる寄稿、出版、講演を通して世間にも広められた。そうした潮流の中でストロヴストルップはデータ抽象の重要性を訴え、リスコフ基底と派生に分けたデータ抽象の階層構造の連結関係(置換原則)について提言した。契約による設計開放閉鎖の原則を提唱するメイヤーが1988年に刊行した『オブジェクト指向ソフトウェア構築』によるEiffel式のクラス理論は高く評価され、Eiffelを現行の模範形とする声も多く上がった。ただしこれは学術寄りの意見でもあったようで、世間のプログラマの間では厳格なEiffelよりも、柔軟で融通の利くC++の人気の方が高まっていた。他方でアラン・ケイのメッセージ・メタファに忠実であろうとする動きもあり、1984年に制作された「Objective-C」はC言語をSmalltalk方向に拡張してメッセージ式を平易化した言語であった。1987年にパロアルト研究所で誕生した「Self」は、Smalltalkのクラスベース設計をより柔軟に平易化したプロトタイプベースを編み出している。これらのメッセージレシーバーは、静的メソッド選択優先の動的ディスパッチ機構という方式でほぼ形式化された。メッセージレシーバーの仕組みは遠隔手続き呼出しオブジェクト要求ブローカーの実装に適していたので、分散システムとオブジェクト指向の親和性を認識させることになった。

コンポーネントとネットワーク(1989 - 97)編集

ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、分散システム構築のための基礎要素としての適性を特に見出される事になり、IBM社Apple社サン社などが1989年に共同設立したOMGは、企業システムネットワーク向け分散オブジェクトプログラミング規格となるCORBAを1991年に発表した。その前年にマイクロソフト社ウェブアプリケーション向けの分散オブジェクトプログラミング技術となるOLEを発表し、1993年にはCOMと称するソフトウェアコンポーネント仕様へと整備した。このCOMの利用を眼目にしてリリースされた「Visual C++」「Visual Basic」はウェブ時代の新しいプログラミング様式を普及させる先駆になった。この頃にデータ抽象、データ隠蔽、アクセスコントロールおよびインターフェースによるプログラムの抽象化といった概念は、カプセル化という用語にまとめられるようになった。クラスの継承が最もオブジェクト指向らしい機能と見なされていたのが当時の特徴であった。継承構造を利用した振る舞いサブタイピング及び動的ディスパッチは多態性という用語に包括された。こうしていわゆるオブジェクト指向の三大要素がやや漠然と確立されている。1996年にサン社がリリースした「Java」は三大要素が強く意識されたクラスベースであり、その中の分散オブジェクト技術はBeansと呼ばれた。類似の技術としてApple社もMacOS上でObjective-Cなどから扱えるCocoaを開発している。また、1994年から96年にかけて「Python」「Ruby」「JavaScript」といったオブジェクト指向スクリプト言語がリリースされ、従来の静的型付けに対する動的型付けと、クラスベースに対する新しいプロトタイプベースの認知度を高めている。

抽象化を旨とするオブジェクト指向ではそのプログラミング自体の抽象化も積極的に推進されている。80年代後半から立ち上げられたオブジェクト指向分析(OOA)やオブジェクト指向設計(OOD)の各手法から導き出される概念モデルを、多角的にチャート化ないしダイアグラム化するための数々のオブジェクト指向開発方法論がOOPSLA界隈の識者たちから発表されるようになり、そこで用いられる形式言語オブジェクトモデリング言語英語版と呼ばれた。これはプログラミングのためのプロトタイプ(ひな型)として重視され、オブジェクト指向ではモデリング言語プログラミング言語が並んでソフトウェア開発の両輪になった。1994年にモデリング言語の代表的な活用例であるGOFデザインパターンが初回発表され、後のオブジェクト指向学習では非常に重視されるようになった。1995年にモデリング言語の標準化を企図したUMLがOOPSLAで初回発表され、1997年にOMGの標準モデリング言語として採用された。

オブジェクト指向言語一覧編集

  • Simula67 1967年 静的
  • Smalltalk 1972年 動的・メッセージ式・純粋系
  • C++ 1983年 静的
  • Objective-C 1984年 静的と動的・メッセージ式
  • Object Pascal 1986年 静的
  • Eiffel 1986年 静的・純粋系
  • Self 1987年 動的・プロトタイプベース・メッセージ式・純粋系
  • Modula-3 1988年 静的
  • Common Lisp(CLOS) 1988年(ANSI規格化は1994年) 動的・多重ディスパッチ
  • Oberon-2 1991年 静的
  • Dylan 1992年 動的・関数型・多重ディスパッチ
  • Lua 1993年 動的・プロトタイプベース
  • Python 1994年(ver1.0) 動的
  • Delphi 1995年 静的
  • Ada 1995年からOOP化 静的
  • Perl 1995年からOOP化 動的
  • Ruby 1995年 動的・純粋系
  • Java 1996年(ver1.0) 静的
  • JavaScript 1996年(first released) 動的・プロトタイプベース
  • OCaml 1996年 静的・関数型
  • Squeak 1996年 動的・メッセージ式
  • ECMAScript 1997年 動的・プロトタイプベース
  • C# 2000年 静的と動的
  • Visual Basic.NET 2001年 静的
  • D言語 2001年 静的
  • Io 2002年 動的・プロトタイプベース・メッセージ式
  • COBOL 2002年からOOP化 静的
  • FORTRAN 2003年からOOP化 静的
  • R言語 2003年からOOP化 動的・関数型・多重ディスパッチ
  • Scala 2003年 静的・関数型
  • Groovy 2003年 動的
  • PHP 2004年からOOP化 静的と動的
  • F# 2005年 静的・関数型
  • MATLAB 2008年からOOP化 動的・関数型
  • Go 2009年 静的
  • Rust 2010年 静的・関数型
  • Kotlin 2011年 静的
  • Ceylon 2011年 静的
  • Dart 2011年 静的・関数型 
  • Elixir 2011年 動的・関数型
  • Julia 2012年 動的・関数型・多重ディスパッチ
  • TypeScript 2012年 静的と動的・関数型
  • Swift 2014年 静的・プロトコル指向
  • Raku 2015年 静的と動的

脚注編集

[脚注の使い方]
  1. ^ “At Utah sometime after Nov 66 when, influenced by Sketchpad, Simula, the design for the ARPAnet, the Burroughs B5000, and my background in Biology and Mathematics, I thought of an architecture for programming. It was probably in 1967 when someone asked me what I was doing, and I said: "It's object-oriented programming".”Alan Kay on the Meaning of “Object-Oriented Programming”
  2. ^ “Our research has concentrated on the development of a rigorous model of computation based on relationship among computational events. The development of this model has been greatly influenced by Seymour Papert's “little people” model of computation, a seminar given by Alan Key at M.I.T. on an early version of Smalltalk, and the work of Church, Fischer, Landin, on formalisms based on the lambda calculus.”Induction and Meta-evaluation
  3. ^ “I didn't like the way Simula I or Simula 67 did inheritance (though I thought Nygaard and Dahl were just tremendous thinkers and designers). So I decided to leave out inheritance as a built-in feature until I understood it better. ”Alan Kay on the Meaning of “Object-Oriented Programming”

関連項目編集