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

削除された内容 追加された内容
Apple改名に伴う変更
RnTknn (会話 | 投稿記録)
(同じ利用者による、間の20版が非表示)
6行目:
{{Wikibooks|オブジェクト指向|オブジェクト指向}}
 
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|''object-oriented programming''}}、略語:OOP)とは[[プログラミング]]技法の一つであり互いに密接な任意の関連性を持つ[[変数 (プログラミング)|データ]]([[変数 (プログラミング)|変数]]または[[プロパティ]])と[[サブルーチン|コード]]([[関数 (プログラミング)|関数]]または[[メソッド (計算機科学)|メソッド]])をひとつにまとめて[[オブジェクト (プログラミング)|オブジェクト]]とし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定義と、それらオブジェクトを相互作用させる様々なプロセスの設定を通して、[[コンピュータプログラム全体]]を構築するソフトウェア開発手法であことを主眼にしている。
 
'''[[オブジェクト指向]]'''という用語言葉自体は、計算機科学者[[アラン・ケイ]]によって生み作り出されている。1962年公開の言語「[[Simula]]言語などにインスパイアされたケイが咄嗟1967年頃に口にしたと伝えられるこの造語は<ref name="造語">“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".”[http://www.purl.org/stefan_ram/pub/doc_kay_oop_en|Dr%7CDr. Alan Kay on the Meaning of “Object-Oriented Programming”]</ref>。この造語は、彼が1972年から開発公開を始めた言語[[Smalltalk]]言語設計を説明する過程明確な用語として発信され1981年頃から知名度を得るようになった。しかしケイが示した80年代半ばになるとオブジェクト指向の要点である[[メッセージパッシング|メッセージング]]の考え方解釈さほど認知される事はなく代わりに[[ク元々のアス (コピュータ)|クラス]]と[[オブジェクト (プログラミング)|オブジェクト]]という仕組みを注目させるだけ・ケイ留まってい。同時に{{疑問点範囲|ケイの手から離れたオブジェクト指向|date=2021-04}}は[[抽象データ型Smalltalk]]を中心にした解釈への様式推移していき、1983年に計算機科学者[[ビャーネ・ストロヴストルップ]]が公開した[[C++]]」が好評を博しの様式に二分されこと。前者、オブジェクト指向に対する世間の理解[[C++メッセージング]]そのモデルの「いう概念が基礎にされ、後者では[[Simula|Simula 67Simula67]]由来スタイルで定着し諸機能を加え。それに基づいて[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモ抽象デフィズムタ型]]といった考え方も後年のスーパーセットが基礎確立されてい。現在では、C++とそのモデルになったSimula67の様式がオブジェクト指向の標準になっている
 
== 特徴 ==
{{独自研究|date=2021-04}}
現行のOOPの世界では[[クラスベース]]と呼ばれるスタイルが{{要出典範囲|大幅な主流にされており、それに次ぐものとして[[プロトタイプベース]]がある|date=2021-04}}。クラスベースのOOP言語は「[[C++]]」「[[Java]]」「[[C Sharp|C#]]」などを代表格にして数多くあり、プロトタイプベースは「[[JavaScript]]」「[[Self]]」を{{要出典範囲|代表にして少数派である|date=2021-04}}。{{独自研究範囲|他のマイナーなスタイルとしては「[[Smalltalk]]」「[[Objective-C]]」のメッセージングベースがあるが、これはあくまで俗称なので正確な定義ではない|date=2021-04}}。「[[Swift (プログラミング言語)|Swift]]」ではプロトコル指向が標榜されている。{{独自研究範囲|現行のOOP言語は上述のスタイルよりも、[[静的型付け]]と[[動的型付け]]による分類の方が一般的になっており、クラスベースといった概念はそれほど認識されなくなっている|date=2021-04}}。静的型付けOOPの{{要出典範囲|代表格|date=2021-04}}は「[[C++]]」「[[Java]]」「[[C Sharp|C#]]」であり、動的型付けOOPの代表格は「[[Python]]」「[[JavaScript]]」「[[Ruby]]」である。{{要出典範囲|近年では[[手続き型プログラミング]]への回帰性や、[[関数型プログラミング]]との融合性による分類も考慮されるようになっている|date=2021-04}}。{{要出典範囲|それでもクラスベースと呼ばれるスタイル概念はOOPの基礎であり根幹であるという事実|date=2021-04}}に変わりはなく、本節でもクラスベースOOPを基準にして説明する。{{独自研究範囲|クラスベースは後述の[[抽象データ型]]をルーツにした標準的OOP思想であり|date=2021-04}}、その名の通り[[クラス (コンピュータ)|クラス]]と[[インスタンス]]の仕組みを中心にしたプログラミングスタイルである。
OOPでは[[クラスベース]]と呼ばれるスタイルが標準にされている。他に[[プロトタイプベース]]と呼ばれる後発のスタイルもあるが、こちらは少数派である。クラスベースのOOP言語は、[[Smalltalk]]様式と[[C++]]様式で二分されており、C++の方がずっと多数派である。C++様式は、[[静的型付け]]と[[動的型付け]]の分類で大別されている。それらの主な特徴を箇条書きするとこうなる。
 
* [[クラスベース]] - クラスのインスタンス化でオブジェクトを構築する。
** [[Smalltalk]]様式 - クラスとインスタンスの[[相対性]]を付与してオブジェクトを体系化している。動的型付け中心。[[メッセージパッシング]]による多態性。
** [[C++]]様式 - クラス(型)とインスタンス(型付け値)に分離してオブジェクトを体系化している。{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}による多態性。
*** [[静的型付け]] - 実行時のクラス構成が基本的に固定されている。
*** [[動的型付け]] - 実行時のクラス構成の変更が前提にされている。
* [[プロトタイプベース]] - オブジェクトのクローンでオブジェクトを構築する。クラスとインスタンスの[[相対性]]をオブジェクトから撤廃して、プロトタイプでオブジェクトを体系化している。動的型付け中心。[[動的束縛|動的バインディング]]による多態性。
 
本稿では最も標準的なクラスベースのC++様式の静的型付けを基準にして説明する。
 
=== クラスとインスタンス ===
OOPの要点である[[クラス (コンピュータ)|クラス]]は、[[データ構造]]とそれを扱うための操作・振る舞いをひとまとめにした一種の[[モジュール|プログラムモジュール]]機能として定義されており、その実装は[[Simula|Simula67]]由来の[[継承 (プログラミング)|継承]]と動的ディスパッチを加えた[[抽象データ型]]のスーパーセットにされていることが多い。クラスのデータ構造は[[レコード型]]や[[構造体]]に似た書式で定義されることが多く、データ構造の要素は言語ごとに[[フィールド (計算機科学)|フィールド]]、[[プロパティ (プログラミング)|プロパティ]]、[[属性]]、メンバ変数などと呼ばれている。クラスに定義される操作・振る舞いは[[メソッド (計算機科学)|メソッド]]やメンバ[[関数 (プログラミング)|関数]]などと呼ばれる。メソッドとは、特定の対象に所属させることを前提にして[[This (プログラミング)|This参照]]を多相シンボルにしたディスパッチコードとしての[[関数 (プログラミング)|関数]]/[[手続き]]を意味している。
{{main|クラス (コンピュータ)}}
 
[[クラス (コンピュータ)|クラス]]は、データの構造(形式)とそれに関連する操作・振る舞いをまとめたものという面がある。
OOP言語の[[クラス (コンピュータ)|クラス]]と、そうでない言語での[[モジュール]]の違いを知ることは、OOPを理解する上でも重要になる。どちらも[[プロシージャ|手続き]]と[[データ]]の複合体であるが、クラスの第一の特徴はそれに[[継承 (プログラミング)|継承]]が備えられていることであり、次に[[This (プログラミング)|This参照]]の機構と、[[継承 (プログラミング)|継承]]構造上の内包的な{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}である。その次になる{{仮リンク|情報隠蔽|en|information hiding}}と、定義と実装に分離しての[[抽象化 (計算機科学)|抽象化]]の機構は、OOP以前の{{仮リンク|モジュラルプログラミング|en|Modular programming}}からのものである。振る舞い抽象を担っている[[インタフェース (抽象型)|インターフェース]]の概念もそちらが先例であったが、データ抽象を担っている[[カプセル化]](情報隠蔽とThis参照の融合)の採用はOOPが最初である。[[継承 (プログラミング)|継承]]構造上の内包的な動的ディスパッチによる[[派生型|サブタイピング]](=[[ポリモーフィズム]])はOOP発祥であるが、それを純粋化すると前述の[[インタフェース (抽象型)|インターフェース]]になる。OOP以前の[[構造化分析設計技法|構造化開発]]のモジュールには情報隠蔽はあるが、[[継承 (プログラミング)|継承]]はなく、[[This (プログラミング)|This参照]]・[[カプセル化]]・[[派生型|サブタイピング]]・[[インタフェース (抽象型)|インターフェース]]といった抽象化機構も持たない。なお、{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}は[[多重ディスパッチ]]中心OOPでは軽視されており、カプセル化は[[プロトタイプベース]]OOPでは軽視されている。従ってOOPを特徴付けている本来の要素とは即ち[[継承 (プログラミング)|継承]]であり、その真偽はともかくとして、継承はプログラムの再利用性と保守性を高めるためのメカニズムと定義されている。
これだけの説明だと[[C言語]]<!--や[[Visual Basic]]系 非OOP?-->などの非OOP言語で使用される[[モジュール]]と同じようだが、
 
クラスには [[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム]](後述)といった考え方や言語機能が導入され、抽象化(abstraction)やコード再利用に役立つ。
C++様式のクラスベースは[[オブジェクト (プログラミング)|オブジェクト]]を、[[型理論]]に沿った[[型システム|型]](type)と[[型付け|型付け値]](term)に分離している。その型の一種であるユーザー定義型(user defined type)がクラスにされており、その型付け値が[[インスタンス]]になっている。ユーザー定義型とは[[構造体]]と同じものであり、OOPでは[[手続き]](のポインタ)も構造体メンバにされている。ユーザー定義型は[[オブジェクト型]]とも呼ばれるが、このオブジェクト型と後節の「[[オブジェクト (プログラミング)|オブジェクト]]」の意味上の繋がりはない。[[クラス (コンピュータ)|クラス]]はインスタンスのひな型であり、[[インスタンス]]はクラスを実体化したものである。実体化=インスタンス化とは対象クラスの全変数内容を決定し、[[ヒープ領域]]の基底アドレス([[This (プログラミング)|This]])を定めた上でそこにメモリ展開するという作業を指している。コンパイル時にその構成が確定されるユーザー定義型は[[静的型付け]]であり、実行時にもその構成を変更できるユーザー定義型は[[動的型付け]]である。
クラスは[[データ型|型]]としての役割りももつ。
 
=== オブジェクトとは ===
クラスの記述において、
[[クラスベース]]言語での「[[オブジェクト (プログラミング)|オブジェクト]]」は、一般的には[[インスタンス]]を指す用語として説明されているが、このような重複語になった背景にはOOPの原点である[[Smalltalk]]からの事情がある。Smalltalkは、全てのプログラム要素は[[オブジェクト (プログラミング)|オブジェクト]]であり、全てのオブジェクトはクラスのインスタンス化であり、クラスもまたオブジェクトであると定義していた。そこでは[[クラス (コンピュータ)|クラス]]もまた[[メタクラス]](型)の[[インスタンス]]化(型付け値)になり、そのメタクラスもまた他のメタクラスのインスタンス化になっていたので、[[クラス (コンピュータ)|クラス]]と[[インスタンス]]は即ちオブジェクトの性質([[相対性]])を指すための言葉になっていた。これが[[C++]]様式では簡素化されて、クラスとインスタンスは[[型システム|型]]と[[型付け|型付け値]]の役割に固定され、メタクラスはクラス構成の動的変更機能に固定されたので、上述のインスタンス化の[[相互再帰]]が失われたオブジェクトは、インスタンスと同じ意味の言葉として残されることになった。またSmalltalkは、オブジェクトは他のオブジェクトと相互作用(interaction)するとも定義しており、この相互作用とは各種演算と同義である。Smalltalkのクラスは型付け値でもあるのでオブジェクトであるが、C++様式のクラスはただの型なので演算対象に出来ないことからオブジェクトではなくなっている。
データの構造は名前を付けた複数のデータ要素をまとめた[[レコード型]]([[構造体]]型)かそれに似た形で定義されることが多く、この要素は(言語によって) [[フィールド (計算機科学)|フィールド]]、データメンバ、[[プロパティ (プログラミング)|プロパティ]]、[[属性]]、メンバ変数 などと呼ばれる。
また、クラスに定義される操作・振る舞いは、(言語によって) [[メソッド (計算機科学)|メソッド]]、メンバ[[関数 (プログラミング)|関数]]、メンバ[[プロシージャ|手続き]] などと呼ばれる。
 
Smalltalk方言の[[Self]]を原点とする[[プロトタイプベース]]は、オブジェクトからクラスとインスタンスの[[相対性]]を無くしたスタイルである。数値・文字列・配列・関数・シンボル・[[構造体]]([[オブジェクト型]])といった[[プリミティブ型|基本的な型]]は備えられているが、これはオブジェクト種類の区別に特化されたものなので、[[型理論]]に沿ったクラスベースの[[型システム|それ]]とは厳密には異なっている。クラス性質を除去したオブジェクトは事実上のインスタンスに一元化されており、その全てが相互作用(interaction)する。オブジェクトの表現はスロット(シンボルとコンテンツのペアデータ)の[[可変長配列]]でなされており、オブジェクトの識別は専ら[[ダックタイピング]]によってなされる。クラス概念が無いのでサブクラス化とインスタンス化は成立せず、代わりにクローン(複製)によってオブジェクトの継承がなされており、クローンはインスタンス化の代替になる。複製元オブジェクトは、複製先オブジェクトのプロトタイプと呼ばれる。
{{独自研究範囲|クラスはデータとメソッドの構成を定義した型であるので、それを計算対象や代入対象になる値として扱うには[[インスタンス]]に実体化(量化)する必要がある。その用法でのクラスはユーザー定義型と呼ばれる。クラスはインスタンスのひな型であり、インスタンスはクラスを量化したものである。ここでの量化とは、そのクラスに属する変数の値を全て決定してメモリに展開する行為を指す。言語によっては後述の[[仮想関数テーブル]]もセットで展開する。インスタンスは別名としてオブジェクトとも呼ばれる。OOPの主役である'''オブジェクト'''の意味と用法は実は曖昧なのが現状であり言語ごとにも違いがある。|date=2021-04}}
 
=== オブジェクト指向の三大要素 ===
{{要出典範囲|[[クラスベース]]OOPの中心である[[抽象デクラス (コンピュータ)|クラス]]の思想に準拠しており|date=2021-04}}、その実装スタイル様式を規定している以下の三項目は、{{要出典範囲|日本では三大要素または三大原則などと呼ばれている|date=2021-04}}。{{独自研究範囲|非OOP言語の[[モジュール]]に三大が、各要素仕様を加えたもがOOP軽視重視と導入方法は言語のクラスなる。カプセル化は[[This (プログラミング)|this参照]]の機構とデータ/メソッドの可視性を指定できる機能、継承は自身のスーパークラスを指定できる機能、ポリモーフィズムは[[オーバーライド]]と[[仮想関数テーブル]]を処理できる機能様々である。
|date=2021-04}}
==== カプセル化 ====
互いに関連するデータとメソッドをまとめてクラスとし、必要なデータとメソッドのみを外部公開し、それ以外をクラス内に隠蔽する機能を[[カプセル化]]と呼ぶ。外部公開されたデータとメソッドはクラス外からの直接アクセスが可能である。内部隠蔽されたデータとメソッドはクラス外からアクセスされないことが保証されこれは{{仮リンク|情報隠蔽|en|information hiding}}と呼ばれる。同クラス所属のメソッドを通してのデータの閲覧と変更はそのデータの抽象化を意味することになりこれは{{仮リンク|Data Abstraction|en|Abstraction (computer science)|label=データ抽象}}と呼ばれる。この二つがカプセル化の要点である。データ抽象を実装するための仕組みでもある[[This (プログラミング)|this参照]]については後節で述べられる。データ閲覧用メソッドはゲッター、データ変更用メソッドはセッターと呼ばれる。データとメソッドの外部公開範囲を、{{独自研究範囲|無制限・任意クラスグループ・派生クラスグループの三段階に分けて定義する機能|date=2021-04}}は[[アクセスコントロール]]と呼ばれる。
 
==== 継承[[カプセル化]] ====
データ構造とそれを扱うためのメソッド群を情報隠蔽の概念と合わせてモジュール化(パッケージ化)するという手法が[[カプセル化]]と呼ばれる。カプセル化されたメソッドは、[[This (プログラミング)|This値]]が暗黙の先頭引数として常に渡されるように実装される。This値とはクラスのデータ構造をメモリ展開するための[[ヒープ領域]]の基底アドレスを指しており、インスタンス化時に確定されたThis値によってメソッドは専用のデータ構造にアクセスできる。専用メソッドを通してのデータ構造の閲覧と変更は、[[抽象データ型]]の考え方に沿ったデータ構造の抽象化を意味することになり、これは{{仮リンク|Data Abstraction|en|Abstraction (computer science)|label=データ抽象}}と呼ばれる。データ閲覧用メソッドはゲッター/アクセッサと呼ばれ、データ変更用メソッドはセッター/ミューテイタと呼ばれる。
{{see also|[[継承 (プログラミング)|継承]]|is-a関係|[[サブクラス (計算機科学)|サブクラス]]}}
{{日本語表現|date=2021年5月|section=1}}
既存クラスのデータ/メソッド構成に任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義する機能を[[継承 (プログラミング)|継承]]と呼ぶ。その差分プログラミング目的の継承よりも、既存構成に抽象メソッドを置いて新規構成にその実体メソッドを置くという{{疑問点範囲|date=2021年5月|オーバーライド目的}}の継承の方が要点にされている。新規構成ではなく実装内容を付け足していくための継承である。
 
{{仮リンク|情報隠蔽|en|information hiding}}とはそのクラスのデータ構造の各要素および各メソッドを必要に応じて内部隠蔽するという概念である。内部隠蔽されたデータ要素とメソッドはそのクラス外部からのアクセスが禁止される。[[抽象データ型]]本来の形式ではデータ構造のみが隠蔽対象になるので、これはデータ隠蔽とも呼ばれる。隠蔽指定外のデータ要素とメソッドは外部公開されて、そのクラス外部からもアクセス可能になる。外部公開の範囲を指定する機能は[[アクセスコントロール]]と呼ばれており、これが内部隠蔽の仕組みを担っている。クラスの[[レキシカルスコープ]]を基準にした段階的なアクセス許可範囲は可視性と呼ばれる。可視性は無制限・任意クラスグループ限定・派生クラスグループ限定・自クラス限定(内部隠蔽)の四段階が[[統一モデリング言語|UML]]では標準にされている。
既存クラスは基底クラス、親クラス、スーパークラスなどと呼ばれ、新しいクラスは派生クラス、子クラス、サブクラスなどと呼ばれる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。
 
==== [[継承 (プログラミング)|継承]] ====
<!-- 概念的に インターフェース継承(型継承、[[is-a関係]]、下位分類)と 実装の継承 の2つの側面があるといったことを書いた方がよさそう。 記述によっては両方の継承関係が同時に生じる。 -->
既存クラスのデータ/メソッド構成に、任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義するという手法が[[継承 (プログラミング)|継承]]と呼ばれる。また、各クラスの共通構成パートを括りだして特有構成パートと分離することでオブジェクトを分類体系化し、同時にその共通構成パートの記号化によってソースコード内の重複記述を削減する機能とも解釈される。これは差分プログラミング目的の継承であり、1990年代までは多用された。2000年代になると[[SOLID]]原則の重視に伴なって、既存構成に抽象メソッドを置いて新規構成にその実体メソッドを置くという[[オーバーライド|メソッドオーバーライド]]を用いるための{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}目的の継承が要点にされるようになっている。データ/メソッドの新規構成ではなく、メソッドの実装内容を付け足していくための継承である。そこでは特にデータ構造を付け足しての階層的なデータの分散配置は倦厭されている。
抽象メソッドを持つクラスは抽象クラスと呼ばれる。
抽象メソッドのみで構成される純粋抽象クラスの継承は、インターフェースの継承(または実装)などと呼ばれて抽象化目的の継承になる。
 
既存クラスはスーパークラス・親クラス・基底クラスなどと呼ばれ、新しいクラスはサブクラス・子クラス・派生クラスなどと呼ばれる。親と子は差分プログラミング重視で用いられ、基底と派生はサブタイピング重視で用いられる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語がある。<!-- 概念的に インターフェース継承(型継承、[[is-a関係]]、下位分類)と 実装の継承 の2つの側面があるといったことを書いた方がよさそう。 記述によっては両方の継承関係が同時に生じる。 -->抽象メソッドを持つクラスは抽象クラスと呼ばれる。基底クラス側で返り値の型と引数リストのみが定義されて実行コードブロックが未定義のままの抽象メソッドは、その派生クラス側の実体メソッドで[[オーバーライド]]される。オーバーライドは遅延結合による多相な[[複雑系]][[アルゴリズム]]を表現するオープン[[再帰]](open recursion)のメカニズムにもなっている。
==== ポリモーフィズム ====
異なる種類のクラスに同一の操作インターフェースを持たせる機能を[[ポリモーフィズム]](多態性)と呼ぶ。{{独自研究範囲|これはクラスの継承関係を利用して、コンパイル時のメソッド名から呼び出されるプロセス内容を実行時に決定するという仕組みを指す|date=2021-04}}。{{独自研究範囲|その実装は{{仮リンク|仮想関数(OOP)|en|Virtual function|label=仮想関数}}と呼ばれており、クラスベースOOPのポリモーフィズムはイコール仮想関数となっている。仮想関数はスーパークラスの抽象メソッドの呼び出しを、それを[[オーバーライド]]したサブクラスの実体メソッドの呼び出しにつなげる機能である。抽象メソッドとオーバーライド機能については後節で述べる。ポリモーフィスムの要点は、同じメソッド名からその実行時に対応した異なる処理内容を呼び出せるようにすることである。|date=2021-04}}
 
抽象メソッドのみで構成される純粋抽象クラスは[[インタフェース (抽象型)|インターフェース]]と呼ばれ、その継承は実装(implementaion)と呼ばれる。実装継承という俗称もある。実装はサブタイピングによる[[Is-a]]関係を完全順守させるためのメカニズムであり、継承とは別個の概念として扱われている。{{仮リンク|モジュラルプログラミング|en|Modular programming}}が先例になる実装は、[[継承 (プログラミング)|継承]]から[[派生型|派生]](subtyping)への先祖返りと言えるものである。
=== インターフェース ===
インターフェースという言葉は一般的な意味でも使われるが、
ここで言う[[インタフェース (抽象型)|インターフェース]]は、
[[抽象型]](抽象クラス)の一種で、抽象メソッドのみで構成されているものである。
言語によってはクラスとは区別される(Javaなど)。
インターフェースはカプセル化を更に突き詰めた仕組みであり、データ抽象とメソッド抽象と情報隠蔽を合わせて実現する{{独自研究範囲|最もOOPらしい機能と言える|date=2021-04}}。
ゲッター、セッター、プロセスになる各抽象メソッドの実装内容は利用者側から隠されて実行時のその都度に決定される。
 
==== コン[[ジションとデションフィズム]] ====
異なる種類のクラスに共通の操作インターフェースを持たせてオブジェクトの振る舞いを抽象化するという手法が[[ポリモーフィズム]](多態性)と呼ばれる。OOPで語られる多態性はもっぱら継承構造を利用した{{仮リンク|サブタイプ多相|en|Subtyping}}を対象にしているが、{{仮リンク|アドホック多相|en|Ad hoc polymorphism}}もサポート的に用いられており、{{仮リンク|パラメトリック多相|en|Parametric polymorphism}}はコンポジションで用いられている。そのサブタイプ多相の設計としてはコンパイル時に確定されたメソッド名から呼び出されるプロセス内容が実行時に決定されるという仕組みを指しており、一つのメソッド名からその実行時状態に合わせた個別のメソッド処理が呼び出されるようにするという演繹的意味と、各クラスの同種機能メソッドを一つの共通メソッドにまとめて実行時状態に合わせたメソッド処理が呼び出されるようにするという帰納的意味がある。
コンポジション(合成)とデリゲーション(委譲)は、{{疑問点範囲|date=2021年5月|継承の原型的仕組みであり、別の言い方をすると合成+委譲を最適化した機能が継承である}}。実装継承は[[is-a]]構造の委譲、合成は[[has-a]]構造の委譲と読み替える事ができる。合成とは、クラスに特定処理の委譲先となる部品クラスを複数持たせた構造であり、合成クラスがデータ/メソッドを要求されて自身が未所持の場合は、対応可能な部品クラスを選択して委譲するという仕組みである。
 
その実装としては[[オーバーライド|メソッドオーバーライド]]機能を活用した仮想関数と、実行時[[パターンマッチング]]機能を活用した総称関数の二つが挙げられる。{{仮リンク|仮想メソッド(OOP)|en|Virtual function|label=仮想関数}}はスーパークラスの抽象メソッドの呼び出しを、それを[[オーバーライド]]したサブクラスの実体メソッドの呼び出しにつなげるという動的ディスパッチ機能である。{{仮リンク|総称関数|en|generic function}}はオブジェクトの実行時[[パターンマッチング]]を使用する独立関数であり、その引数にされた各オブジェクトの型(=クラス)の組み合わせに従って実行コードブロックを選択決定するという[[多重ディスパッチ]]機能である。
その要求判別と選択過程を自動化したのが(実装)継承であり、部品クラスを親クラスに置き換えて暗黙の委譲先にしたものである。しかしその暗黙委譲は実際に参照されるデータ/メソッドの把握を困難にするという欠点も明らかになったので、合成の価値が再認識されるようになった。既存構成に新規構成を付け足していく差分プログラミング目的では、継承よりも合成を用いる方がよいと考えられている{{要出典|date=2021年5月}}。
 
=== コンポジションとデリゲーションとジェネリクス ===
{{仮リンク|オブジェクトコンポジション|en|Object composition|label=コンポジション (合成)}}と[[委譲|デリゲーション]](委譲)は、[[継承 (プログラミング)|継承]]を帰納的に分解した仕組みと言えるものであり、または合成と委譲による連携を演繹的に最適化した仕組みが継承であるとも言える。OOPにおける合成と委譲は、OOP原点の[[Smalltalk]]が[[Simula|Simula67]]発の継承機能をオブジェクトの再帰構成という観点から再解釈したものがデザイン上のルーツになっている。継承は例外も多いが[[Is-a]]の委譲であるのに対して、合成は[[Has-a]]の委譲と読み替えることができる。
 
合成とは、特定処理の委譲先になる部品クラスの1個以上を持たせたクラス構造であり、そのクラスがとある処理を要求されてそれに対応できるデータ/メソッドを持っていない場合は、それに対応できる部品クラスを選択して処理を委譲するという仕組みである。その要求判別と選択過程を自動サーチ化したものが継承であり、部品クラスを基底クラスに置き換えて暗黙の委譲先にしたものである。しかしその自動サーチは、クラス階層に分散配置されているデータ/メソッドのどれが実際にアクセスされるのかという把握を困難にしたので、ここで差分プログラミング用途の継承の欠点が取り沙汰されるようになり、2000年代になるとクラスの機能拡張と分類体系化では、継承と合成の使い分けが重視されるようになった。
 
[[ジェネリックプログラミング|ジェネリクス]](総称化)は、オブジェクトの[[データ構造]]を汎用化して、それに汎用[[アルゴリズム]]の数々を適用できるようにした技術である。様々なデータ要素を内包するコンポジション(合成)オブジェクトは[[コンテナ (データ型)|コンテナ]](List/Set/Mapなど)と呼ばれ、その要素の型を型変数化することで汎用的な[[データ構造]]を表現し、その要素の型はコンテナのインスタンス化時に与えられる型パラメータによって決定される。ジェネリクスは[[データ構造]]と[[アルゴリズム]]の柔軟な[[ソフトウェアコンポーネント|コンポーネント化]]を促進させた。また、[[圏論]]の[[圏 (圏論)|圏]]に見立てられた[[コンテナ (データ型)|コンテナ]]および[[対象 (圏論)|対象]]に見立てられたデータ要素の入れ子構造と、[[射 (圏論)|射]]に見立てられた[[派生型|サブタイピング]]の融合は、[[共変性と反変性 (計算機科学)|共変性と反変性]]の手法に発展した。
 
=== 動的ディスパッチとメッセージパッシング ===
{{仮リンク|動的ディスパッチ|en|Dynamic dispatch}}、OOPの[[ポリモーフィズム]]原型基礎的仕組みであり、例えば継承構造上での[[This (プログラミング)|thisThis]]参照によるシングルディスパッチを最適化した機能が[[仮想関数であ]]になっている。動的ディスパッチは<!--コンパイル時の-->に確定されたメソッド名から呼び出されるメソッド内容(実行コードブロック)が実行時に決定される仕組み全般を指している総称用語であり、る。メソッド名を基軸して与えられた各引数の型の組み合わせって、実行コードブセスックが選択分岐される仕組みを意味するシングルディスパッチと[[多重ディスパッチ]]を包括している。一つの先頭引数の型がプ[[パターンマッチング]]固定で実行コードブセスックが選択に影響す決定(ディスパッチ)されるのはシングルになり二つ以上そうでないなら多重になる。
 
メッセージパッシングでは前述の引数の型に加えてだけでなく、メソッド名も実行時に解釈される要素にされておりこでただのシンボルとして扱わるメソッド名はセレクタと呼ばれている。セレクタはメッセージ式を基本文とするSmalltalk様式のOOPで用いられる。<code>object selector: param</code>ような書式でオブジェクトの共通窓口となるメッセージレシーバーにセレクタと引数値で構成されたメッセージが送られる。また、<code>object.call(method_name, param)</code>のような書式でオブジェクトの共通窓口関数をコールするのもメッセージパッシングと呼ばれる。これは[[Remote Procedure Call|遠隔手続きコール呼出し]]や[[Object Request Broker|オブジェクト要求ブローカー]]で用いられており分散オブジェクトの標準的なインターフェース機構になっている。関数名(=メソッド名(関数名)も実行時に解釈されるという特徴を指してメッセージパッシングと呼ぶ。よく用いらメッセージレシーバー内では、渡さセレクタ対応プの文字列照合の条件分岐によって実行コードブセスを自動ックが選択化してコンパイル時最適化した仕組みされることメソッドになり多くこれOOP原点のSmalltalk、引名をコと[[This (プログラミパイル時決定すグ)|This]]が与えられ関数呼び出しその実行コードブロックをメソッド同類になっ呼んでいた。
 
=== プロトタプベンターフェース ===
[[インタフェース (抽象型)|インターフェース]]は、[[カプセル化]]を更に突き詰めた概念であり、[[継承 (プログラミング)|継承]]の[[派生型|サブタイピング]]用法を更に突き詰めた概念である実装(implementation)を体現している仕組みである。インターフェースは、[[オブジェクト (プログラミング)|オブジェクト]]の情報隠蔽とデータ抽象とメソッド抽象を合わせて表現する。[[クラス (コンピュータ)|クラス]]から見たインターフェースは、自身のサービスのモデリングであり、この作法は実現(realization)と呼ばれる。OOPの[[インタフェース (抽象型)|インターフェース]]は、基本的には抽象メソッドのみで構成される[[抽象型]]と定義されている。[[ソフトウェアコンポーネント]]間の相互通信媒体として用いられることが多く、[[SOLID|SOLID原則]]の重視に伴ないクラス間の[[結合度|結合]]にも多用される。
{{see|プロトタイプベース}}
[[クラスベース]]のクラスと実体化とインスタンスは、[[プロトタイプベース]]ではプロトタイプと複製とオブジェクトに置き換わる。プロトタイプとオブジェクトは双方とも、プロパティとメソッドを自由に付け替え可能にされており{{独自研究範囲|これは[[動的束縛|動的バインディング]]とも呼ばれ、そのプロパティとメソッドの構成による型は[[ダックタイピング]]で判別される。この特徴は同時に[[ポリモーフィズム]]になる|date=2021-04}}。
<!-- その用法は[[関数オブジェクト]]と変数オブジェクト(値オブジェクト)に大別され、前者のプロパティは[[二階述語論理]]、後者のメソッドは[[高階述語論理]]の表現体になり、それ自体が[[メタデータ|メタ]]視点から抽象化されたオブジェクトには[[カプセル化]]という概念は必要でなくなる。 -->
 
各言語での導入様式としては、抽象メソッドのみで構成される純粋抽象クラスが基本形にされており、インスタンス化はできない継承専用クラスになる。多重継承が前提にされている。インターフェースの抽象メソッドのメソッド内容(実行コードブロック)は、それを実装したクラスの同名メソッドで記述されることになる。インターフェースの各抽象メソッドはセッター・ゲッター・プロセスなどとして動作し、その実装内容は利用者側からは隠されて実行時のその都度に決定されることになる。
{{独自研究範囲|[[継承 (プログラミング)|継承]]では委譲先になる部品オブジェクトの自由な合成が重視されており、その部品は[[トレイト]]と呼ばれる事が多くその合成は多重継承と同義になる。前述のコンポジションは[[has-a]]構造であるが、トレイトは[[is-a]]構造の合成である。トレイトの実装はもっぱら構造的型付けで判別される。|date=2021-04}}
 
=== 多重ディスパッチとミックスインとトレイト ===
{{独自研究範囲|[[プロトタイプベース]]は動的な[[関数型プログラミング]]に似た性質になっているが、オブジェクトの柔軟な用法に対しての一定の枠組みが必要であるとも考えられて静的な[[クラス (コンピュータ)|クラス]]定義が積極的に導入されるようになり、現状では関数型とOOPのハイブリッドのようなパラダイムに落ち着いている。|date=2021-04}}
[[多重ディスパッチ]]は、オブジェクトの{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}を、オブジェクトの実行時[[パターンマッチング]]に置き換えた[[ポリモーフィズム]]・アプローチである。サブタイピングが同名アルゴリズムを個々の派生クラスに分散記述するのに対して、多重ディスパッチは個々の派生クラスの同名アルゴリズムを独立関数内で一括記述する。その独立関数が多重ディスパッチではメソッドと呼ばれるが、正確にはディスパッチ先になる個々の実行コードブロックがメソッドであり、その多重定義で総称メソッド({{仮リンク|総称関数|en|generic function}})と呼ばれる。総称メソッドは1個以上のオブジェクトを引数にし、その各引数オブジェクトの型(クラス)の組み合わせに従って、実行コードブロックを選択決定(ディスパッチ)する。その型[[パターンマッチング]]では、クラスに付加された[[アノテーション]]識別([[マーカーインタフェース|マーカーインターフェース]])の方が重視されることもあり、これがアドホック多相とサブタイプ多相の双方で継承を解釈できる[[ミックスイン]]の原点になっている。
 
[[ミックスイン]](Mix-in)は、[[スーパークラス (計算機科学)|上位クラス]]からの機能取得と[[サブクラス (計算機科学)|下位クラス]]への機能注入を主体にした[[継承 (プログラミング)|継承]]アプローチであり、そこでは上位クラスと下位クラスの[[Is-a関係]]が軽視されていることも特徴である。これは[[サブタイプ|サブタイピング]]特化の実装継承とは反対に、差分プログラミング用法に特化させた継承と言えるものである。ただしこの差分プログラミングはあくまで[[メソッド (計算機科学)|メソッド]]限定である。こちらも[[多重継承]]が前提であり、インスタンス化はできない継承専用クラス(Mix-inクラス)を扱っている。Mix-inクラスの代表的な実装形態は[[トレイト]]である。トレイトはメソッドの集合体であり、そのメソッド集合を一つの機能にした分類体系化が可能であり、そのメソッド間で状態を共有するためのデータメンバも所有できることがある。トレイトは機能注入用のメソッド実体と、[[オーバーライド]]用の[[関数プロトタイプ|メソッド定義]]の双方を持てるが、[[インタフェース (抽象型)|インターフェース]]とは異なり前者のメソッド実体の方が中心である。Mix-inの設計は各言語で多様化しており、Mix-inクラスは各言語によって[[トレイト]]・モジュール・ロール・プロトコル・[[型クラス]]などの様々な形態で導入されている。クラスをそのままMix-in化できる言語もあり、[[関数オブジェクト]]をMix-in化できる言語もあり、メソッド実装も可能にしたインターフェースをMix-in化できる言語もある。[[トレイト]]のMix-inは{{仮リンク|構造的型付け|en|Structural type system}}で扱われることが多く、従来の[[クラス (コンピュータ)|クラス]]の継承と[[インタフェース (抽象型)|インターフェース]]の実装が{{仮リンク|記名的型付け|en|Nominal type system}}で扱われることと対比されている。
=== メッセージング ===
{{独自研究|date=2021-04}}
メッセージングはオブジェクト指向の父である{{要出典範囲|[[アラン・ケイ]]が最重視していた源流思想である|date=2021-04}}。これは当時の[[LISP]]風プログラミングの変化球と言えるものであり、[[関数型プログラミング]]と対比させると分かりやすくなる。関数([[写像]])を値に適用するという関数型の基本形に対して、メッセージングでは写像をただのシンボル(=セレクタ)にしており、写像を融合させた値(=オブジェクト)にセレクタを送ると、その値専用の写像がセレクタ別に呼び出されるようになっている。写像から計算式を取り除いてただの象徴記号にしたものがセレクタであり、値と写像を融合したものがオブジェクトである。セレクタには引数としてのオブジェクトを続かせられる。セレクタ用法はたらい回し的なデリゲーションに適しているようである。メッセージングベースのOOPは恐らく永遠の途上段階にあるので、このセレクタ構文を用いているか否かが現在に到るまでの類別基準になっている。
 
== 歴史 ==
1954年に初の[[高水準言語]]・[[FORTRAN]]が登場すると、開発効率の劇的な向上と共にソフトウェア要求度も自然と高まりを見せてプログラム規模の急速な拡大が始まった。それに対応するために肥大化したメインルーチンを[[サブルーチン]]に分割する手法と、[[スパゲティプログラム|スパゲティ化]]した[[Goto文|goto命令]]を[[制御構造|制御フロー文]]に置き換える手法が編み出され、これらは1960年に公開された言語「[[ALGOL|ALGOL60]]」で形式化された。当時のALGOLは[[アルゴリズム]]記述の一つの模範形と見なされたが、それと並行して北欧を中心にした計算機科学者たちはより大局的な観点によるプログラム開発技法の研究を進めていた。
 
=== Simulaの開発(1962 - 72) ===
1962年、ノルウェー計算センターで[[モンテカルロ法]]シミュレーションを運用していた計算機科学者[[クリステン・ニゴール]]は、[[ALGOL|ALGOL60]]を土台にしてProcessと呼ばれる[[コルーチン]]機構を加えたプログラミング言語「[[Simula]]」を公開制作し、続けてその拡張にも取り組んだ。ニゴールの同僚で、1963年にSimulaを[[メインフレーム|汎用機]][[UNIVAC I|UNIVAC]]系統上で運用できるように実装した計算機科学者[[オルヨハン・ダール]]は、Processにローカル変数構造を共有する手続き(サブルーチン)を加えてパッケージ化する言語仕様を考案し、これは一定任意の変数と手続きをまとめる[[モジュール|プログラムモジュール]]と同類の機能になった。程なくしてALGOL60コンパイラに準拠していての限界を悟ったニゴールとダールは、1965年からSimulaを一から再設計するように方針転換した。その過程で彼らは、計算機科学者[[アントニー・ホーア]]が考案して1962年のSIMSCRIPT([[FORTRAN]]用のスクリプト)に実装していたRecord Classを参考にしている。Record Classはソースコード水準の抽象表現記号を、各[[メインフレーム|汎用機]]に準拠した[[マシンコード]]水準の実装符号に落とし込む段階的データ構造のプログラム概念であった。これをモデルにした[[継承 (プログラミング)|継承]]と、その継承構造を利用した仮想手続き(仮想関数)の仕組みも考案され、上述のパッケージ化されたProcess(モジュール)に継承と仮想手続きの両機能を加えたものを「[[クラス (コンピュータ)|クラス]]」と定義し、クラスをメモリに展開したものを「[[オブジェクト (プログラミング)|オブジェクト]]」と定義する言語仕様がまとまり、1967年に「[[Simula|Simula67]]」が初公開された。オブジェクトという用語は、[[MIT]]の計算機科学者[[アイバン・サザランド]]が1963年に開発した[[Sketchpad]]の設計上にあったObjectが先例であった。[[Sketchpad]]は[[CAD]]と[[GUI]]の元祖)原点として知られており、後述設計内[[Smalltalk]]のモチーフの一つあるObjectが先例であもなている。Simula67コンパイラはまず汎用機[[UNIVAC I|UNIVAC]]上で運用され、翌年から汎用機[[バロース B5000|バロースB5500]]などでも稼働されて北欧、ドイツ、ソ連の各研究機関へと広まり、1972年には[[IBMメインフレーム|IBM汎用機]][[System/360]]などにも導入されて北米全土にも広まった。その主な用途は離散事象および物理シミュレーションであった。
 
=== 構造化プログラミングの提唱(1969 - 75) ===
[[Simula]]の普及と前後して1960年代半ばになるとプログラム規模の際限ない肥き拡に伴ソフトウェア開発現場負担増大難航顕著頻発するようになり、いわゆる[[ソフトウェア危機]]問題が計算機科学分野全般で取り沙汰されるようになった。その解決に取り組んだ計算機科学者[[エドガー・ダイクストラ]]は、1969年のNATOソフトウェア工学会議で「[[構造化プログラミング]]」という論文を発表し[[トップダウン設計とボトムアップ設計|トップダウン設計]]、段階的な[[抽象化 (計算機科学)|抽象化]]、階層的な[[モジュール化]]、共同詳細化(抽象データ構造と抽象ステートメントのjoint)を連携させて具象化する概念)といった構造化手法を提唱した。ダイクストラ言う構造化と論旨開発効率を高めるため[[正当性 (計算機科学)|プログラム正当性]]検証技術確立であり、[[分割統治法数学的証明|数学証明]]に倣った視点でソースコード意味適切に分割て抽象化することが勧められていた。なおしかしこの構造化プログラミングは後に曲解されて[[制御構造|制御フロー文]](順次・分岐・反復)中心にした解釈の方勧める論旨で世間に広まることにな定着、ダイクストラ本来の論旨であったプログラムモジュールを抽象化して扱おうとす考え方は当時の世間には伝わらなかった。共同詳細化は抽象データ構造を専用ステートメントを通して扱うというする概念である。これはSimulaり、Simula67の手続きを通してクラス内の変数にアクセスするという仕組みをモチーフていた。段階的な抽象化と階層的なモジュール化は時系列的にも、SIMSCRIPTの段階的データ構造とSimura67の継承による階層的クラス構造を模倣したものであが先例になていた。[[エドガー・ダイクストラ|ダイクストラ]]、[[アントニー・ホーア|ホーア]]、[[オルヨハン・ダール|ダール]]の三は1972年に『構造化プログラミング』と題した共著を上梓していることから互いの研鑽関係が証明されている。おり、その階層的プログラム構造という章の中でダールは、Simulaの目指した設計理念を更に明らかにした。
 
1974年に[[MIT]]の計算機科学者[[バーバラ・リスコフ]]は「[[抽象データ型]]」というプログラム概念を提唱し、ダイクストラが提示した上述のモジュールの共同詳細化をその振る舞いによって[[セマンティクス|意味内容]]がされる抽象データという考え方でより明解に形式化した。一方、19701975年に構造化言語[[Pascal]]を開発していた計算機科学者[[ニクラウス・ヴィルト]]は、ダイクストラによる共著出版後の1975年にモジュール機能を主題にした言語[[Modula-2|Modula]]を提示してと共に{{仮リンク|モジュラプログラミング|en|Modular programming}}を提唱した。このパラダイムでは、[[モジュール]]を仕様定義とコード/データ実装に分離しての、前者による抽象化と後者の情報隠蔽が備えられて、これは[[インタフェース (抽象型)|インターフェース]]の実装という概念の先例になっている。また、1970年代後半から[[IBM]]社を中心にした研究者たちが([[エドワード・ヨードン]]など)[[サブルーチン]]モジュールと[[データ構造]]を連携させる[[構造化分析設計技法|構造化]]のパラダイムを生み出発表、こちらではモジュールの抽象指向は倦厭されて具象的な[[段階的詳細化法|段階的詳細化]]が重んじられた。当時は具象指向の方に軍配が上がり、[[構造化プログラミング|構造化開発]]は1980年代までのソフトウェア開発の主流になっている。このようにいささか奇妙ではあるが、Simulaのクラスとオブジェクトというプログラム概念は、巷で言われる構造化[[モジュール|プログラムモジュール]]の登場からモジュや[[構造分析設計技法|構造化開発]]へといった進化の流れとは関係なく、しかもその前段階においてさながら彗星のように生まれたパラダイムであっていた。
 
=== Smalltalkとオブジェクト指向の誕生(1972 - 81) ===
Simula発のProcessとクラスの示した可能性は、[[パロアルト研究所]]の計算機科学者[[アラン・ケイ]]による「メッセージング」という考え方のヒントになった。ケイはプログラム内のあらゆる要素をオブジェクトとして扱い、オブジェクトはメッセージの送受信でコミュニケーションするという独特のプログラム理論を提唱した。それには従来の関数呼び出しをセレクタの実行時解釈に置き換えて積極的な[[委譲]]を推進するメッセージ式と、プログラムコードとしても解釈できるデータ列を送信してそれを任意のタイミングで評価(eval)することで新たなデータを導出できるなどのアイディアが盛り込まれていた。これらの遅延結合パラダイムは非同期通信や単方向通信への可能性をも開いており、この発想の背景には[[LISP]]の影響があった。メッセージを駆使するオブジェクトの構築には、Simula発のそれに[[プラトン]]の[[イデア論]]を重ね合わせた[[クラス (コンピュータ)|クラス]]と[[インスタンス]]の仕組みが導入された。オブジェクトとメッセージングの構想に基づいて開発された「[[Smalltalk]]」はプログラミング言語と[[GUI]]フレームワークを併せたものとなり、1972年に[[データゼネラルNova]]上での1000行程度のBASICを使った試作(概念実証)を経て、翌1973年に新開発された[[Alto|ゼロックスAlto]]上で本格稼働された。Smalltalkの設計を説明するためにケイが考案した「[[オブジェクト指向]]」という用語はここで初めて発信された。またケイのメッセージング構想は[[MIT]]の計算機科学者[[カール・ヒューイット]]に能動的な[[プロセス代数]]を意識させて<ref name="アクター">“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.”[https://dl.acm.org/doi/abs/10.1145/512927.512942|Actor Induction and Meta-evaluation]</ref>、1973年発表の[[アクターモデル]]のヒントにもなっている。しかし委譲の多用とデータ列が常にコード候補としても扱われる処理系は、当時のコンピュータには負荷が大きく実用的な速度を得られないという問題にすぐ直面した。Smalltalk-74(新たに開発された[[BitBLT]]を使った高速描画版Smalltalk-72)からSmalltalk-76の過程で、やむなくメッセージは(多くの場合)関数の動的コールに、メソッドはパターンマッチ処理から単なる関数へ置き換えられるなど構想時の柔軟さが失われるほど最適化された。また、ケイの留保した継承機構<ref name="継承">“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. ”[http://www.purl.org/stefan_ram/pub/doc_kay_oop_en|Dr. Alan Kay on the Meaning of “Object-Oriented Programming”]</ref>も導入されてオブジェクトは抽象データ型の性格も有するようになった。
 
1980年のSmalltalk-80は、元々はメッセージを重視していたケイを自嘲させるほど同期的で双方向的で手続き的なオブジェクト指向へと変貌していた。それでも動的ディスパッチと[[委譲]]でオブジェクトを連携させるスタイルは画期的であり、1994年に発表される[[デザインパターン (ソフトウェア)|デザインパターン]]の模範にもされている。1981年に当時の著名なマイコン専門誌『[[Byte (magazine)|BYTE]]』が、Smalltalkとその理念であるオブジェクト指向を紹介して世間の注目を集める契機になったが、ケイの思惑に反して技術的関心を集めたのはクラスの仕組みの方であった。オブジェクト指向は知名度を得るのと同時に、Simula発の[[クラス (コンピュータ)|クラス]]([[継承 (プログラミング)|継承]]と動的ディスパッチ)および[[抽象データ型]](データ抽象とデータ隠蔽)にマウントされて解釈されるようになり、それらのコンセプトがケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。
Simula発のProcessとクラスの示した可能性は、[[パロアルト研究所]]の計算機科学者[[アラン・ケイ]]によるオブジェクト重視と「メッセージング」という考え方のヒントになった。ケイはプログラム内のあらゆる要素をオブジェクトとして扱い、オブジェクトはメッセージの送受信でコミュニケーションするという独特のプログラム理論を提唱した。それには関数適用風の書式を用いたオブジェクト同士の多種多様な[[委譲|デリゲーション]]と、プログラムコードとしても解釈できるデータ列を送信してそれを評価(''eval'')することで新たなデータを導出できるなどのアイディアが盛り込まれていた。オブジェクトが送るか受け取ったメッセージは任意のタイミングで評価できるので非同期通信や単方向通信をも可能にしていた。この発想の背景には[[LISP]]の影響があった。オブジェクトとメッセージングの構想に基づいて開発された「[[Smalltalk]]」はプログラミング言語と[[GUI]]運用環境を併せたものとなり、1972年に[[データゼネラルNova]]上での1000行程度のBASICを使った試作(概念実証)を経て、翌1973年に新開発された[[Alto|ゼロックスAlto]]上で本格稼働された。Smalltalkの設計を説明するためにケイが考案した「[[オブジェクト指向]]」という用語はここで初めて発信された。またケイのメッセージング構想は[[MIT]]の計算機科学者[[カール・ヒューイット]]に能動的な[[プロセス代数]]を意識させて<ref name="アクター">“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.”[https://dl.acm.org/doi/abs/10.1145/512927.512942|Actor Induction and Meta-evaluation]</ref>、1973年発表の[[アクターモデル]]のヒントにもなっている。しかしデリゲーションの多用とデータ列が常にコード候補として扱われる処理系は、当時のコンピュータには負荷が大きく実用的な速度を得られないという問題にすぐ直面した。Smalltalk-74(新たに開発された[[BitBLT]]を使った高速描画版Smalltalk-72)からSmalltalk-76の過程で、やむなくメッセージは(多くの場合)関数の動的コールに、メソッドはパターンマッチ処理から単なる関数へ置き換えられるなど構想時の柔軟さが失われるほど最適化された。また、ケイの留保した継承機構<ref name="継承">“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. ”[http://www.purl.org/stefan_ram/pub/doc_kay_oop_en|Dr. Alan Kay on the Meaning of “Object-Oriented Programming”]</ref>も導入されてオブジェクトは抽象データ型の性格も有するようになった。
 
1980年のSmalltalk-80は、元々はメッセージを重視していたケイを自嘲させるほど同期的で双方向的で手続き的なオブジェクト指向へと変貌していた。それでも動的ディスパッチと[[委譲]]でオブジェクトを連携させるスタイルは画期的であり、1994年に発表される[[デザインパターン (ソフトウェア)|デザインパターン]]の模範にもされている。1981年に当時の著名なマイコン専門誌『[[Byte (magazine)|BYTE]]』がSmalltalkとケイ提唱のオブジェクト指向を紹介して世間の注目を集める契機になったが、ケイの思惑に反して技術的関心を集めたのはクラス機構の方であった。オブジェクト指向は知名度を得るのと同時に、Simula発の[[クラス (コンピュータ)|クラス]]とそれを理論面から形式化した[[抽象データ型]]を中心に解釈されるようになり、それらの考案者がケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。
 
=== C++の開発と普及(1979 - 88) ===
[[Simula]]を研究対象にしていた[[ベル研究所|AT&Tベル研究所]]の計算機科学者[[ビャーネ・ストロヴストルップ]]は、1979年からクラス付きC言語の開発制作に取り組み、1983年に「[[C++]]」を公開した。C++で実装された[[クラス (コンピュータ)|クラス]]は、Simula譲り由来の[[継承 (プログラミング)|継承]]と仮想関数に加えて、段階的な[[レキシカルスコープ]]の概念をクラス構造に応用した[[アクセスコントロール]]を備えていた。C++で確立されたアクセスコントロールはカプセル化の元情報隠蔽なっよるデータ抽象を提示したがコードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(''not just'')オブジェクト指向言語であると明言している。1986年にソフトウェア技術者[[バートランド・メイヤー]]が開発制作した「[[Eiffel]]」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性/手続き/関数の三種構成で、手続きで属性を変更し関数で属性を参照閲覧するという形式に限定されており、これは[[抽象データ型の[[セマンティクス|振る舞い意味論]]に沿った忠実な実装であった。アクセスコントロールはモジュC++のとは異なるクープログラミングの情報隠蔽に沿ったス指名方式になりされ、仮想関数機能は延期手続き/関数として実装された。
 
1986年から[[Association for Computing Machinery|ACM]]が[[OOPSLA|]]を年度開催するようになり、オブジェクト指向会議は従来の[[構造化プログラミング|構造化開発]](OOPSLA)を年度開催に代わる技術と、そて明確に意識され始めた。OOPSLAのプログラミング言語セクションでは[[抽象データ型]]の流れ汲む基礎にした[[クラス (コンピュータ)|クラス]]・パラダイムが主要テーマにされ、それを標準化するための数々のトピックが議題に上げられている。[[モジュール|モジュール分割]]、情報隠蔽、[[抽象化 (計算機科学)|抽象化]]、[[再利用|再利用性]]、[[継承 (プログラミング)|階層構造]]、複合構成、情報隠蔽、実行時多態、[[動的束縛]]、[[総称型]]、[[永続性]]、[[並行性]]、[[ガベージコレクション|自動メモリ管理]]といったものがそうであり、参画した識者たちによる寄稿、出版、講演を通して世間にも広められた。そうした潮流の中で[[ビャーネ・ストロヴストルップ|ストロヴストルップ]]はデータ抽象の重要性を訴え、[[バーバラ・リスコフ|リスコフ]]は[[上位概念、下位概念、同位概念および同一概念|基底と派生]]に分けたデータ抽象の階層構造の連結関係([[リスコフの置換原則|階層構造の連結関係置換原則]]について提言した。[[契約による設計]]と[[開放/閉鎖原則|開放閉鎖原則]]を提唱する[[バートランド・メイヤー|メイヤー]]が1988年に刊行した『オブジェクト指向ソフトウェア構築』によるEiffel式のクラス理論名著と高く評価され、Eiffelを現行の模範形とする声も多く上がった。ただしこれは学術寄りの意見でもあったようで、世間のプログラマの間では厳格なEiffelよりも柔軟で融通の利くC++の人気の方が高まっていた。他方でオブジェクト指向本来[[アラン・ケイ]]原点であるメッセージ・メタファに忠実であろうとする動きもあり、1984年に開発制作された「[[Objective-C]]」はSmalltalkC言語モデルSmalltalk方向拡張してそれメッセージ式を平易化した言語であった。1987年に[[パロアルト研究所]]で誕生した「[[Self]]」は、Smalltalkの[[クラスベース]]設計をより柔軟に平易化した[[プロトタイプベース]]を編み出している。これらのメッセージレシーバーは静的メソッド機構選択優先の動的ディスパッチ機構という方式で実装ほぼ形式化された。メッセージレシーバの仕組みは[[遠隔手続き呼出し]]/[[Object Request Broker|オブジェクト要求ブローカー]]の実装に適していたので[[分散システム]]とオブジェクト指向の親和性を認識させることになった。
 
=== コンポーネントとネットワーク(1989 - 97) ===
ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、[[分散システム]]構築のための基礎要素としての適性を特に見出される事になり、[[IBM|IBM社]]、[[Apple|Apple社]]、[[サン・マイクロシステムズ|サン社]]などが1989年に共同設立した[[Object Management Group|OMG]]は、企業システムネットワーク向け分散オブジェクトプログラミング規格となる[[CORBA]]を1991年に発表した。その前年に[[マイクロソフト|マイクロソフト社]]は[[ウェブアプリケーション]]向けの分散オブジェクトプログラミング技術となる[[OLE]]を発表し、1993年には[[Component Object Model|COM]]と称する[[ソフトウェアコンポーネント]]仕様へと整備した。この[[Component Object Model|COM]]の利用を眼目にしてリリースされた「[[Microsoft Visual C++|Visual C++]]」「[[Visual Basic]]」は[[World Wide Web|ウェブ]]時代の新しいプログラミング様式を普及させる先駆になった。この頃にデータ抽象、データ隠蔽、[[アクセスコントロール]]および[[インタフェース (抽象型)|インターフェース]]によるプログラムの抽象化は、総じて[[カプセル化]]の概念でまとめられるようになった。クラスの[[継承 (プログラミング)|継承]]が最もオブジェクト指向らしい機能と見なされていたのが当時の特徴であった。継承構造を利用した振る舞いサブタイピング及び動的ディスパッチは[[多態性]]という用語に包括された。こうしていわゆるオブジェクト指向の三大要素がやや漠然と確立されている。1996年にサン社がリリースした「[[Java]]」は三大要素が強く意識された[[クラスベース]]であり、その中の分散オブジェクト技術は[[JavaBeans|Beans]]と呼ばれた。類似の技術としてApple社も[[MacOS]]上で[[Objective-C]]などから扱える[[Cocoa]]を開発している。また、1994年から96年にかけて「[[Python]]」「[[Ruby]]」「[[JavaScript]]」といったオブジェクト指向スクリプト言語がリリースされ、従来の[[静的型付け]]に対する[[動的型付け]]と、[[クラスベース]]に対する新しい[[プロトタイプベース]]の認知度を高めている。
 
抽象化を旨とするオブジェクト指向ではそのプログラミング自体の抽象化も積極的に推進されている。80年代後半から立ち上げられた[[オブジェクト指向分析設計|オブジェクト指向分析]](OOA)や[[オブジェクト指向設計]](OOD)の各手法から導き出される[[コンセプトモデル|概念モデル]]を、多角的に[[フローチャート|チャート化]]ないし[[ダイアグラム|ダイアグラム化]]するための数々のオブジェクト指向開発方法論が[[OOPSLA]]界隈の識者たちから発表されるようになり、そこで用いられる[[形式言語]]は{{仮リンク|オブジェクトモデリング言語|en|Object-modeling language}}と呼ばれた。これはプログラミングのためのプロトタイプ(ひな型)として重視され、オブジェクト指向では[[モデリング言語]]と[[プログラミング言語]]が並んでソフトウェア開発の両輪になった。1994年にモデリング言語の代表的な活用例である[[ギャング・オブ・フォー (情報工学)|GOF]][[デザインパターン (ソフトウェア)|デザインパターン]]が初回発表され、後のオブジェクト指向学習では非常に重視されるようになった。1995年にモデリング言語の標準化を企図した[[統一モデリング言語|UML]]がOOPSLAで初回発表され、1997年に[[Object Management Group|OMG]]の標準モデリング言語として採用された。
ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、[[分散システム]]構築のための基礎要素としての適性を特に見出される事になり、[[IBM|IBM社]]、[[Apple]]、[[サン・マイクロシステムズ|サン社]]などが1989年に共同設立した[[Object Management Group|OMG]]は、企業システムネットワーク向け分散オブジェクトプログラミングの標準規格となる[[CORBA]]を1991年に公開した。その前年に[[マイクロソフト|マイクロソフト社]]は[[ウェブアプリケーション]]向けの分散オブジェクト技術となる[[OLE]]を発表し、1993年には[[Component Object Model|COM]]と称する[[ソフトウェアコンポーネント]]仕様へと整備した。この[[Component Object Model|COM]]の利用を眼目にしてリリースされた「[[Microsoft Visual C++|Visual C++]]」「[[Visual Basic]]」は[[World Wide Web|ウェブ]]時代の新しいプログラミング様式を普及させる先駆になった。この頃に[[抽象データ型]]のメソッドを通したデータ抽象、データ隠蔽、[[アクセスコントロール]]および分散オブジェクトの[[インタフェース (情報技術)|インターフェース]]機構によるプログラムの抽象化といった概念は、[[カプセル化]]という用語にまとめられるようになった。クラスの[[継承 (プログラミング)|継承]]が最もオブジェクト指向らしい機能と見なされていたのが当時の特徴であった。継承構造を利用した振る舞いサプタイピングは[[多態性]]という用語に包括された。こうしていわゆるオブジェクト指向の三大要素がやや漠然と確立されている。1996年にサン社がリリースした「[[Java]]」は三大要素が強く意識された[[クラスベース]]であり、その中の分散オブジェクト技術は[[JavaBeans|Beans]]と呼ばれた。類似の技術としてアップル社も[[MacOS]]上で[[Objective-C]]などから扱える[[Cocoa]]を開発している。また、1994年から96年にかけて「[[Python]]」「[[Ruby]]」「[[JavaScript]]」といったオブジェクト指向スクリプト言語がリリースされ、従来の[[クラスベース]]に対する新しい[[プロトタイプベース]]を定着させている{{疑問点|date=2021年5月|title=これだと Python と Ruby もプロトタイプベースであるかのようにも見える。}}。1994年の[[ギャング・オブ・フォー (情報工学)|GOF]][[デザインパターン (ソフトウェア)|デザインパターン]]の発表と、1997年に[[Object Management Group|OMG]]が標準[[モデリング言語]]として採用した[[統一モデリング言語|UML]]は、オブジェクト指向プログラミングの標準化を促進させた。
 
== 代表的なオブジェクト指向言語一覧 ==
ここではクラスベースの記述は省略している。
 
<div style="{{column-count|2}}">
* [[Simula|Simula 67]] 1967年
* [[SmalltalkSimula|Simula67]] 19721967 静的
* [[Smalltalk]] 1972年 動的・メッセージ式・純粋系
* [[C++]] 1983年
* [[Objective-C++]] 19841983 静的
* [[Objective-C]] 1984年 静的と動的・メッセージ式
* [[Object Pascal]] 1986年
* [[EiffelObject Pascal]] 1986年 静的
* [[SelfEiffel]] 19871986 静的・純粋系
* [[Self]] 1987年 動的・プロトタイプベース・メッセージ式・純粋系
* [[Common Lisp]]([[CLOS]]) 1988年(ANSI規格化は1994年)
* [[Modula-3]] 1988年 静的
* [[Common Lisp]]([[CLOS]]) 1988年(ANSI規格化は1994年) 動的・多重ディスパッチ・[[The Art of the Metaobject Protocol|メタオブジェクト]]
<!-- :[[クラスベース]]のオブジェクト指向。メソッド記述の関数呼び出し形式への統合、[[多重ディスパッチ]]、クラスの動的な再定義等を特徴とする。-->
* [[PythonOberon-2]] 19941991 静的
*[[Dylan]] 1992年 動的・多重ディスパッチ
* [[Java]] 1995年
*[[Lua]] 1993年 動的・プロトタイプベース
* [[Delphi]] 1995年
* [[RubyPython]] 19961994(ver1.0) 動的
* [[JavaScriptDelphi]] 19961995 静的
*[[Ada]] 1995年からOOP化 静的
* [[C Sharp|C#]] 2000年
* [[ScalaPerl]] 20031995からOOP化 動的
* [[KotlinRuby]] 20111995 動的・純粋系
* [[TypeScriptJava]] 20121996(ver1.0) 静的
* [[JavaScript]] 1996年(first released) 動的・プロトタイプベース
* [[Swift (プログラミング言語)|Swift]] 2014年
*[[OCaml]] 1996年 静的・関数型
*[[Squeak]] 1996年 動的・メッセージ式
*[[ECMAScript]] 1997年 動的・プロトタイプベース
*[[C Sharp|C#]] 2000年 静的と動的
*[[Visual Basic .NET|Visual Basic.NET]] 2001年 静的
*[[D言語]] 2001年 静的
*[[Io (プログラミング言語)|Io]] 2002年 動的・プロトタイプベース・メッセージ式・純粋系
*[[COBOL]] 2002年からOOP化 静的
*[[FORTRAN]] 2003年からOOP化 静的
*[[R言語]] 2003年からOOP化 動的・関数型・多重ディスパッチ
* [[Scala]] 2003年 静的・関数型
*[[Groovy]] 2003年 動的
*[[PHP (プログラミング言語)|PHP]] 2004年からOOP化 静的と動的
*[[F Sharp|F#]] 2005年 静的・関数型
*[[MATLAB]] 2008年からOOP化 動的・関数型
*[[Go (プログラミング言語)|Go]] 2009年 静的
*[[Rust (プログラミング言語)|Rust]] 2010年 静的・関数型
* [[Kotlin]] 2011年 静的
*[[Ceylon]] 2011年 静的
*[[Dart]] 2011年 静的・関数型 
*[[Elixir (プログラミング言語)|Elixir]] 2011年 動的・関数型
*[[Julia (プログラミング言語)|Julia]] 2012年 動的・関数型・多重ディスパッチ
* [[TypeScript]] 2012年 静的と動的・関数型
*[[Swift (プログラミング言語)|Swift]] 2014年 静的・プロトコル指向
*[[Raku]] 2015年 静的と動的
</div>
 
== 関連項目用語一覧 ==
ここでは日本語ページ化されている項目のみ列挙している。
{{Wikibooks|オブジェクト指向|オブジェクト指向}}
<div style="{{column-count|3}}">
* [[メッセージ (コンピュータ)]]
* [[クラスベース]]
* [[メソッド (計算機科学)]]
*[[プロトタイプベース]]
* [[フィールド (計算機科学)]]
*[[メッセージ (コンピュータ)|メッセージ]]
*[[クラス (コンピュータ)|クラス]]
*[[インスタンス]]
*[[フィールド (計算機科学)|フィールド]]
*[[プロパティ (プログラミング)|プロパティ]]
*[[メソッド (計算機科学)|メソッド]]
* [[インスタンス変数]]
* [[クラス変数]]
* [[クラス (コンピューストラク)]]
* [[メタクラトラクタ]]
* [[インスタンスカプセル化]]
* [[プロトタイプベース]]
* [[カプセル化]]
* [[継承 (プログラミング)|継承]]
*[[ポリモーフィズム|多態性]]
* [[Is-a|Is-a関係]]
*[[This (プログラミング)|This]]
* [[Has-a|Has-a関係]]
* [[ミックスインIs-a]]
* [[抽象クラスHas-a]]
* [[ダック派生型|サブタイピング]]
*[[ダックタイピング]]
* [[委譲]]
* [[SOLID|SOLID原則ミックスイン]]
*[[スーパークラス (計算機科学)|スーパークラス]]
* [[プログラミング言語]]
*[[サブクラス (計算機科学)|サブクラス]]
* [[デザインパターン (ソフトウェア)|GOFデザインパターン]]
*[[抽象クラス]]
* [[オブジェクト指向モデリング]]
*[[メタクラス]]
* [[オブジェクト指向分析設計]]
* [[オブジェクト指向ーバーライド]]
*[[仮想関数テーブル]]
* [[オブジェクトデータベース]]
*[[菱形継承問題]]
* [[トップダウン設計とボトムアップ設計]]
*[[仮想継承]]
* [[オブジェクト関係マッピング]]
*[[インタフェース (抽象型)|インターフェース]]
 
*[[トレイト]]
* [[抽象型]]
*[[オブジェクト型]]
*[[型クラス]]
*[[委譲]]
*[[多重ディスパッチ]]
*[[ダブルディスパッチ]]
*[[多重定義|オーバーロード]]
*[[アノテーション]]
*[[コンテナ (データ型)|コンテナ]]
*[[ボックス化]]
*[[ジェネリクス]]
*[[共変性と反変性 (計算機科学)|共変性と反変性]]
*[[モジュール]]
*[[ソフトウェアコンポーネント]]
*[[リフレクション (計算機科学)|リフレクション]]
*[[モンキーパッチ]]
*[[メッセージ転送]]
*[[型システム]]
*[[オブジェクト指向分析設計]]
*[[オブジェクト指向モデリング]]
*[[統一モデリング言語|UML]]
*[[契約による設計]]
*[[デザインパターン (ソフトウェア)|GOFデザインパターン]]
*[[GRASP]]
* [[SOLID]]
</div>
 
== 脚注 ==