「オブジェクト指向プログラミング」の版間の差分

削除された内容 追加された内容
m "Template:" を含むテンプレート呼び出し
歴史
45行目:
 
== 歴史 ==
1954年に初の[[高水準言語]]「[[FORTRAN]]」が開発されると、開発効率の劇的な向上と同時にソフトウェア要求度も自然と高まりを見せて、開発を求められるプログラム規模も急速に拡大化した。それに対応するために肥大化したメインルーチンを[[サブルーチン]]に分割する手法と、[[スパゲティプログラム|スパゲティ化]]した[[Goto文|goto命令]]を[[制御構造|制御構造文]]に置き換える手法が編み出され、これらは1960年に公開された言語「[[ALGOL|ALGOL60]]」で形式化された。当時のALGOLは[[アルゴリズム]]記述の一つの模範形と見なされたが、それと並行して北欧を中心にした計算機科学者たちはより大局的な観点によるプログラム設計技法の研究を進めていた。
オブジェクト指向プログラミングという考え方が生まれた背景には、計算機の性能向上によって従来より大規模な[[ソフトウェア]]が書かれるようになってきたということが挙げられる。大規模なソフトウェアが書かれコードも複雑化してゆくにつれ、ソフトウェア開発コストが上昇し、[[1960年代]]には「[[ソフトウェア危機]] ({{Lang|en|software crisis}})」といったようなことも危惧されるようになってきた。そこでソフトウェアの[[再利用 (プログラミング)|再利用]]、[[部品化 (プログラミング)|部品化]]といったようなことを意識した仕組みの開発や、[[ソフトウェア開発工程]]の体系化('''[[ソフトウェア工学]]''' ({{Lang|en|software engineering}}) の誕生)などが行われるようになった。
 
'''Simulaの開発(1962~1972年)'''
このような流れの中で、プログラムを構成するコードとデータのうち、コードについては[[プロシージャ|手続き]]や[[関数 (プログラミング)|関数]]といった仕組みを基礎に整理され、その構成単位を[[ブラックボックス]]とすることで再利用性を向上し、部品化を推進する仕組みが提唱され'''[[構造化プログラミング]]''' ({{Lang|en|structured programming}}) として{{要出典範囲|date=2019年2月|[[1967年]]}}に[[エドガー・ダイクストラ]] ({{Lang|en|Edsger Wybe Dijkstra}}) らによってまとめあげられた(プログラミング言語の例としては[[Pascal]] [[1971年]])。なお、それに続けて「しかしデータについては相変わらず主記憶上の記憶場所に置かれている限られた種類の[[基本データ型]]の値という比較的低レベルの抽象化から抜け出せなかった。これはコードはそれ自身で意味的なまとまりを持つがデータはそれを処理するコードと組み合わせないと十分に意味が表現できないという性質があるためであった。」といったように、ほぼ間違いなく説明されている。
 
1962年、ノルウェー計算センターで[[モンテカルロ法]]シミュレーションを運用していた計算機科学者[[クリステン・ニゴール]]は、[[ALGOL|ALGOL60]]をモデルにしたプログラミング言語「[[Simula]]」を公開するに到り、また更なる拡張にも取り組んだ。ニゴールの同僚で、Simulaを[[メインフレーム|汎用機]][[UNIVAC I|UNIVAC]]系統上で運用できるように実装した計算機科学者[[オルヨハン・ダール]]は、手続き(サブルーチン)をパッケージ化する言語仕様を考案した。程なくしてALGOL60コンパイラに準拠していての限界を悟ったニゴールとダールは、1965年からSimulaを一から再設計するように方針転換した。その過程で両名は、計算機科学者[[アントニー・ホーア]]が考案してSIMSCRIPT([[FORTRAN]]用のスクリプト)に実装していたRecord Classを模範にした。Record Classはソースコード水準の抽象表現を、各[[メインフレーム|汎用機]]に準拠した[[マシンコード]]水準の実装符号に落とし込む段階的データ構造のプログラム概念であった。彼らの構想は、[[継承 (プログラミング)|継承]]と[[ダイナミックバインディング|動的バインディング]](仮想関数)機能を備えた[[クラス (コンピュータ)|クラス]]と、それをメモリに展開した[[オブジェクト (プログラミング)|オブジェクト]]という言語仕様にまとめられて、1967年に「[[Simula|Simula 67]]」が初公開された。オブジェクトという用語は、[[MIT]]の計算機科学者[[アイバン・サザランド]]が開発した[[Sketchpad]]([[CAD]]と[[GUI]]の先例)の設計にあったObjectが先例であった。Simula 67コンパイラはまず[[UNIVAC I|UNIVAC]]上で運用され、翌年から汎用機[[バロース B5000|バロースB5500]]などでも稼働されて北欧、ドイツ、ソ連の各研究機関へと広まり、1972年には[[IBMメインフレーム|IBM汎用機]][[System/360]]などにも導入されて北米全土にも広まった。その主な用途は物理シミュレーションであった。
そこでデータを構造化し、ブラックボックス化するために考え出されたのが、データ形式の定義とそれを処理する手続きや関数をまとめて一個の構成単位とするという考え方で'''[[モジュール]]''' ({{Lang|en|module}}) と呼ばれる概念である([[プログラミング言語]]の例としては[[Modula-2]] 1979年)。しかし定義とプログラム内の実体が一対一に対応する手続きや関数とは異なり、データはその形式の定義に対して値となる実体([[インスタンス]]と呼ばれる)が複数存在し、各々様々な寿命を持つのが通例であるため、そのような複数の実体をうまく管理する枠組みも必要であることがわかってきた。そこで単なるモジュールではなく、それらのインスタンスを整理して管理する仕組み(例えば[[クラス (コンピュータ)|クラス]]とその[[継承 (プログラミング)|継承]]など)まで考慮して生まれたのが[[オブジェクト (プログラミング)|オブジェクト]]という概念である(プログラミング言語の例としては1967年の[[Simula|Simula 67]]<!--言語機能としての「クラス」はSimula 67から-->)。
 
'''構造化プログラミングの提唱(1969~1978年)'''
Simulaのオブジェクトとクラスというアイデアは異なる二つの概念に継承される。一つはシステム全てをオブジェクトの集合と捉え、オブジェクトの相互作用を'''メッセージ'''に喩えた「[[オブジェクト指向]]」である。オブジェクト間の相互作用をメッセージの送受と捉えることで、オブジェクトは受信したメッセージに見合った手続き単位(≒関数)を自身で起動すると考える。結果オブジェクトは自身の持つ手続きのカプセル化を行うことができ、メッセージが同じでもレシーバオブジェクトによって行われる手続きは異なる――[[ポリモーフィズム|多相性]](ポリモーフィズム)を実現した(このメッセージを受け実行される手続き単位は、メッセージで依頼されたことを行うための「手法」の意味で[[メソッド (計算機科学)|メソッド]]と呼ばれる)。この思想に基づき作られたのが[[Smalltalk]]([[1972年]])であり、[[オブジェクト指向]]という言葉はこのとき[[アラン・ケイ]]によって作られた。
 
[[Simula|Simula67]]の普及と前後して1960年代半ばになると、プログラム規模の際限ない肥大化に伴う開発現場の諸問題が浮き彫りになり、いわゆる[[ソフトウェア危機]]が計算機科学分野全般で取り沙汰されるようになった。ソフトウェア危機問題の解決に取り組んだ計算機科学者[[エドガー・ダイクストラ]]は、1969年のNATOソフトウェア工学会議で「[[構造化プログラミング]]」という論文を発表し、その中でトップダウン設計、段階的な[[抽象化 (計算機科学)|抽象化]]、階層的な[[モジュール化]]、統合詳細化といった構造化手法を提唱した。プログラムを構造化すればその規模に関わらず[[正当性 (計算機科学)|正当性]]の証明が可能になるというのが論文の主張であった。統合詳細化は抽象データ構造を専用サブルーチンを通して扱うという概念である。段階的な抽象化と階層的なモジュール化の方は、SIMSCRIPTの段階的データ構造と、Simura67の継承による階層的クラス構造に倣っていることは時系列的にも明らかであり、実際に[[エドガー・ダイクストラ|ダイクストラ]]、[[アントニー・ホーア|ホーア]]、[[オルヨハン・ダール|ダール]]の三名は共同して1972年に『構造化プログラミング』と題した著書を上梓している。その階層的プログラム構造という章の中でダールは、Simula67の目指した設計を更に明らかにした。1974年に計算機科学者[[バーバラ・リスコフ]]とステファン・ジルは「[[抽象データ型]]」というプログラム概念を提唱した。その中で統合詳細化は、[[セマンティクス|振る舞い]]によって定義される抽象データという考え方でより明解に形式化され、データ階層とモジュール階層の繋がりは[[上位概念、下位概念、同位概念および同一概念|上位概念と下位概念]]の[[リスコフの置換原則|置き換え原則]]の確立によって明確に標準化された。1970年に構造化言語[[Pascal]]を開発していた計算機科学者[[ニクラウス・ヴィルト]]はダイクストラの理論を参考にした上で、モジュール化言語[[Modula-2]]を1978年に公開しモジューラプログラミングというパラダイムを生み出している。このように些か奇妙ではあるが、Simulaのクラスとオブジェクトは[[ALGOL]]を原点にしながらも、巷で言われる構造化からモジュール化へといった進化の流れとは関係なく、しかもその前段階においてさながら彗星のように生まれたパラダイムであった。
一方、Smalltalkとは別にSimulaの影響を受け作られた[[C++]]([[1979年]])は[[抽象データ型]]のスーパーセットとしてのクラス、オブジェクトに注目し、オブジェクト指向をカプセル化、継承、多相性をサポートするものと再定義した(その際、実行時速度重視およびコンパイラ設計上の制約により、変数メタファである[[動的束縛]]の特徴は除外された)。これらは当初[[抽象データ型]]、[[派生]]、[[メソッド (計算機科学)#仮想関数|仮想関数]]と呼ばれ、オブジェクトのメンバ関数を実体ではなくポインタとすることで、継承関係にあるクラスのメンバ関数の[[オーバーライド]](上書き)を可能にしたことで、多相性を実現した(この流儀では'''メッセージメタファ'''はオブジェクト指向に必須ではないものと定義し、オブジェクトの持つ手続きをメソッドとは呼ばず[[メソッド (計算機科学)|メンバ関数]]と呼ぶ)。この他、Smalltalkにある[[動的束縛]]の類似的な機能としてオーバーロード([[多重定義]])が実装されている。
 
'''Smalltalkとオブジェクト指向の提唱(1971~1980年)'''
 
Simulaのオブジェクトとクラスというアイデアは異なる二つの概念に継承される。一つはシステム全てをオブジェクトの集合と捉え、オブジェクトの相互作用を'''メッセージ'''に喩えた「[[オブジェクト指向]]」である。オブジェクト間の相互作用をメッセージの送受と捉えることで、オブジェクトは受信したメッセージに見合った手続き単位(≒関数)を自身で起動すると考える。結果オブジェクトは自身の持つ手続きのカプセル化を行うことができ、メッセージが同じでもレシーバオブジェクトによって行われる手続きは異なる――[[ポリモーフィズム|多相性]](ポリモーフィズム)を実現した(このメッセージを受け実行される手続き単位は、メッセージで依頼されたことを行うための「手法」の意味で[[メソッド (計算機科学)|メソッド]]と呼ばれる)。この思想に基づき作られたのが[[Smalltalk]]([[1972年]])であり、[[オブジェクト指向]]という言葉はこのとき[[アラン・ケイ]]によって作られた。
 
Smalltalkはこの「全てをオブジェクトとその相互作用で表現する」というデザインに立ち設計されたため、全てをファイルと捉える'''ファイル指向[[オペレーティングシステム]]'''からの脱却と、プログラムをフロー制御された手続きと捉える'''手続き型言語'''からの脱却が行われた。そのためSmalltalkは自身が'''オブジェクト指向オペレーティングシステム'''でもあること、メッセージ・パッシングなどの特徴を持った。これは当時のプログラム言語としては特異的であり、[[ガベージコレクション|ガベージコレクタ]]を必要とし、高度な最適化が試される前のバイトコード[[インタプリタ]]で実行される処理の重さも手伝って先進的ではありながら普及しがたいものであると捉えられた。また、メッセージでの多相性は、変数へのオブジェクトの[[動的束縛]]が前提となるため、静的型チェック機構でのサポートが難しく、C++等の実行時性能重視の言語にとって実装から除外すべき特徴となった。
 
'''C++の誕生(1979~1985年)'''
 
一方、Smalltalkとは別にSimulaの影響を受け作られた[[C++]]([[1979年]])は[[抽象データ型]]のスーパーセットとしてのクラス、オブジェクトに注目し、オブジェクト指向をカプセル化、継承、多相性をサポートするものと再定義した(その際、実行時速度重視およびコンパイラ設計上の制約により、変数メタファである[[動的束縛]]の特徴は除外された)。これらは当初[[抽象データ型]]、[[派生]]、[[メソッド (計算機科学)#仮想関数|仮想関数]]と呼ばれ、オブジェクトのメンバ関数を実体ではなくポインタとすることで、継承関係にあるクラスのメンバ関数の[[オーバーライド]](上書き)を可能にしたことで、多相性を実現した(この流儀では'''メッセージメタファ'''はオブジェクト指向に必須ではないものと定義し、オブジェクトの持つ手続きをメソッドとは呼ばず[[メソッド (計算機科学)|メンバ関数]]と呼ぶ)。この他、Smalltalkにある[[動的束縛]]の類似的な機能としてオーバーロード([[多重定義]])が実装されている。
 
C++の創始者[[ビャーネ・ストロヴストルップ]]は、Smalltalkが目指したある種の理想の追求には興味が無く、現用としての実用性を重視した。そのため、C++の再定義した「オブジェクト指向」は既存言語の拡張としてオブジェクト指向機能を実装できることでブレイクスルーを迎え急速に普及する。Smalltalkが単なるメソッドの動的呼び出しをメッセージ送信に見立て、呼び出すメソッドが見つからないときのみメッセージをハンドリングできるようにした「省コスト版」の機構を発明し以降それを採用するに至った経緯も手伝って、'''メッセージ送信'''という考え方はやや軽視されるようになり、オブジェクト指向とはC++の再定義したものと広く認知されるようになった。
 
'''オブジェクト指向の普及(1985年~)'''
 
[[1980年]]代後半に次々と生まれたオブジェクト指向分析・設計論は、[[Smalltalk]]を源流とするオブジェクト指向を基に組み立てられた。そのころSmalltalkは商用展開こそされていたが広く普及しているとは言えず、一般には[[C++]]での[[実装]]が多くを占めた。しかしC++はSmalltalkと思想的にかなり異なる点や、同様のことを実現する際の実装面での複雑さや制約が問題とされた。このニーズを受けC++の提示した抽象データ型にクラスを適用する現実的な考え方と親しまれたALGOL系の構文を踏襲しつつ、内部的には柔軟なSmalltalkのオブジェクトモデルを採用し、'''メソッド'''などの一部用語やリフレクション、実行時動的性などSmalltalk色も取り入れた[[Java]]が注目を集めた([[1995年]]に登場。元々はモバイル機器向け言語処理系として開発された)。程なくSmalltalkやSELFで達成された[[仮想機械|仮想マシン(バイトコードインタープリタ)]]高速化技術の転用により実用的速度を得、バランス感覚に長けたJavaの台頭によって[[オブジェクト指向開発]]に必要な要素の多くが満たされ、[[1990年代]]後半からオブジェクト指向は広く普及するようになった。