コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

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

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
SUMIM.ST (会話 | 投稿記録)
Alto誕生前の実装の記述を追加。他、細部も修正 Smalltalkとオブジェクト指向の誕生(1972 - 81)
m 仮リンクの修正
 
(30人の利用者による、間の221版が非表示)
1行目: 1行目:
{{翻訳中途|[[:en:Object-oriented programming]](13:57, 15 November 2021 UTC)の翻訳|date=2021年11月}}
{{複数の問題
|独自研究=2018年2月
|出典の明記=2019年2月
}}
[[ファイル:Object oriented design object.jpg|境界|右|フレームなし|265x265ピクセル]]
{{プログラミング・パラダイム}}
{{プログラミング・パラダイム}}
{{Wikibooks|オブジェクト指向|オブジェクト指向}}


'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|''object-oriented programming''}}、略語:OOP)とは、互いに密接な関連性を持つ[[変数 (プログラミング)|データ]]([[変数 (プログラミング)|変数]]または[[プロパティ]])と[[サブルーチン|コード]]([[関数 (プログラミング)|関数]]または[[メソッド (計算機科学)|メソッド]])をひとつにまとめて[[オブジェクト (プログラミング)|オブジェクト]]とし、それぞれ異なる性質と役割を持せたオブジェクトの様々な定義と、それらオブジェクトを相互に作用させる様々なプロセスの設定を通して、プログラム全体を構築するソフトウェア開発手法である。
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|object-oriented programming}}, OOP)とは、[[オブジェクト (プログラミング)|オブジェクト]]いう概念に基づい[[プログラミングパラダイ]]の一つである。


OOPでは、相互に作用するオブジェクトを組み合わせてプログラムを設計する{{sfn|Kindler|Krivy|2011}}{{sfn|Lewis|Loftus|2008|loc=§1.6 "Object-Oriented Programming"}}。
'''[[オブジェクト指向]]'''という用語自体は、計算機科学者[[アラン・ケイ]]によって生み出されている。1962年公開の言語「[[Simula]]」にインスパイアされたケイが咄嗟に口にしたとされるこの造語は、彼が1972年から開発公開を始めた「[[Smalltalk]]」の言語設計を説明する中で発信されて1981年頃から知名度を得た。しかしケイが示したオブジェクト指向の要点である[[メッセージパッシング|メッセージング]]の考え方はさほど認知される事はなく、代わりに[[クラス (コンピュータ)|クラス]]と[[オブジェクト (プログラミング)|オブジェクト]]という仕組みを注目させるだけに留まっている。同時にケイの手から離れたオブジェクト指向は[[抽象データ型]]を中心にした解釈へと推移していき、1983年に計算機科学者[[ビャーネ・ストロヴストルップ]]が公開した「[[C++]]」が好評を博したことで、オブジェクト指向に対する世間の理解は「[[C++]]」とそのモデルの「[[Simula|Simula 67]]」のスタイルで定着した。それに基づいて[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム]]といった考え方も後年に確立された。


OOPの方法として、[[クラスベース]]OOPと[[プロトタイプベース]]OOPがある。
== 特徴 ==
クラスベースOOPでは、オブジェクトが属する集合として[[クラス (コンピュータ)|クラス]]を定義し、クラス定義からその[[インスタンス]]としてオブジェクトを生成する。
プロトタイプベースOOPでは既存のオブジェクト(プロトタイプ)を複製し、プロトタイプの複製に変更を加えることで様々な対象を表すオブジェクトを生成する。


広く使われているプログラミング言語の多く、例えば[[C++]]や[[Java]]や[[Python]]などは、[[マルチパラダイムプログラミング言語|マルチパラダイム]]であるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は[[命令型プログラミング|命令型]]や[[手続き型プログラミング]]との組み合わせで用いられる。
=== クラスベースとプロトタイプベース ===
OOPという[[プログラミングパラダイム|パラダイム]]は、[[クラスベース]]と[[プロトタイプベース]]の二つのサブパラダイムに大別されている。クラスベースの代表格は「[[C++]]」「[[Java]]」「[[C Sharp|C#]]」であり、プロトタイプベースの代表格は「[[Python]]」「[[JavaScript]]」「[[Ruby]]」である。前者は[[クラス (コンピュータ)|クラス]]と[[インスタンス]]の仕組みを中心にしており、後者は{{仮リンク|メタオブジェクトプロトコル|en|Metaobject|label=}}の仕組みを基礎にしている。前者は[[静的型付け]]を重視しており、後者は[[動的型付け]]を重視している。2000年代以降になるとプロトタイプベースもクラスの仕組みを積極的に取り入れるようになったので、純粋なプロトタイプベースの存在感は失われつつある。本節でもクラスベースを基準にして説明する。


== 歴史 ==
=== クラスとインスタンス ===
OOPの要点である[[クラス (コンピュータ)|クラス]]とは、端的に言うと変数と関数をひとまとめにしたものであり、手続きを付けたデータ構造体とも解釈される。コンパイル時定義の静的型付けが普通である。クラスに属する[[変数 (プログラミング)|変数]]はデータメンバまたは'''データ'''と総称され、言語別にフィールド、[[プロパティ (プログラミング)|プロパティ]]、[[属性]]、メンバ変数といった名称になっている。クラスに属する[[関数 (プログラミング)|関数]]はもっぱら'''メソッド'''、メンバ関数、メンバ手続きといった名称になっている。これだけの説明だと[[C言語]]や[[Visual Basic .NET|Visual Basic]]系などの非OOP言語で使用される[[モジュール]]と、OOP言語のクラスは同じものに見えるが双方の間には明確な違いがあり、モジュールに'''抽象'''(''abstraction'')の考え方とその機能を導入したものがクラスである。抽象化のための機能とは後述の[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム]]を指している。
[[File:oop-uml-class-example.png|frame|right|[[統一モデリング言語|UML]]による[[クラス (コンピュータ)|クラス]]の表記法。この {{code|Button}} クラスは、データを表す[[変数 (プログラミング)|変数]](図中 {{code|xsize}} など)と[[メソッド (計算機科学)|関数]](図中 {{code|draw()}} など)を持つ。一般的なクラスは[[継承 (プログラミング)|継承]]により[[サブクラス (計算機科学)|サブクラス]]を持つことができる。また、オブジェクトはクラスの[[インスタンス]]である。]]
<!-- 以上、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->
[[アラン・ケイ]]によれば “{{en|object-oriented}}”([[オブジェクト指向]])という言葉は、1967年ごろケイ自身が考案したものであるという{{sfn|Meaning|2003}}。しかし、現在のオブジェクト指向プログラミングという文脈における「オブジェクト」や「指向」を表す用語が初めて登場したのは、1950年代後半から1960年代前半にかけての[[マサチューセッツ工科大学|マサチューセッツ工科大学(MIT)]]においてである。
1960年代初頭の[[人工知能]]グループ界隈では、「オブジェクト」はプロパティ(属性)を持つ個体識別可能なアイテム([[LISP]]の atom)を意味していた{{sfn|LISP 1 Programmers Manual|1960|p=88f}}{{sfn|LISP 1.5 Programmers Manual|1962|p=105}}。
後にケイは、1966年にLISPの内部構造を詳細に理解したことが彼の考え方に強い影響を与えたと述べている{{sfn|Meaning|2003}}。


{{Quote box
クラスはデータとメソッドの構成を定義した型であるので、それを計算対象や代入対象になる値として扱うには[[インスタンス]]に実体化(量化)する必要がある。その用法でのクラスはユーザー定義型と呼ばれる。クラスはインスタンスのひな型であり、インスタンスはクラスを量化したものである。ここでの量化とは、そのクラスに属する変数の値を全て決定してメモリに展開する行為を指す。言語によっては後述の[[仮想関数テーブル]]もセットで展開する。インスタンスは別名としてオブジェクトとも呼ばれる。OOPの主役である'''オブジェクト'''の意味と用法は実は曖昧なのが現状であり言語ごとにも違いがある。
|quote = 私は、オブジェクトとは、生物の細胞やネットワーク上の個々のコンピュータのようもの、そしてそれらのコミュニケーションは専らメッセージによって行なわれるもの、と考えていました (つまり、メッセージングは最初から存在していたのですが、プログラミング言語でメッセージングを実用的かつ効率的に行う方法を見つけるまでには時間がかかりました)。
|author = アラン・ケイ
|source = {{harv|Meaning|2003}}
|width = 50%
}}


MITにおける初期の例としては、この他にも、1960年から1961年にかけて[[アイバン・サザランド]]が作成した[[Sketchpad]]が挙げられる。サザランドは、1963年の技術レポートの用語集 (Sketchpadに関する自身の博士論文をもとにしたもの)で、グラフィカルなインタラクションに特化しているとはいえ「オブジェクト」と「インスタンス」の概念を定義している (クラスの概念は"master"または"definition"として把握されている)。{{sfn|Sutherland|1963}}
=== オブジェクト指向の三大要素 ===
また、MIT版の[[ALGOL]]であるAED-0では、データ構造 (この言語の方言では"plexes"と呼称)と手続きを直接結びつけ、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるようなものの萌芽がみられる。{{sfn|Nygaard|Dahl|1978}}
[[クラスベース]]OOPは[[抽象データ型]]の思想に準拠しており、その実装スタイルを規定した以下の三項目は、日本では三大要素または三大原則などと呼ばれている。非OOP言語の[[モジュール]]に三大要素仕様を加えたものがOOP言語のクラスになる。カプセル化は[[This (プログラミング)|this参照]]の機構とデータ/メソッドの可視性を指定できる機能、継承は自身のスーパークラスを指定できる機能、ポリモーフィズムは[[オーバーライド]]と[[仮想関数テーブル]]を処理できる機能である。


1962年、[[クリステン・ニゴール]]は{{仮リンク|ノルウェー計算センター|en|Norwegian Computing Center}}でシミュレーション言語のプロジェクトを開始した。これは彼が以前に用いた[[モンテカルロ法]]と実世界のシステムを概念化する仕事に基づくものであった。[[オーレ=ヨハン・ダール]]が正式にプロジェクトに参加し、[[UNIVAC I]] (UNIVAC 1107) 上で動作する[[Simula]]プログラミング言語が設計された。Simulaは、[[クラス (コンピュータ)|クラス]]や[[オブジェクト (プログラミング)|オブジェクト]]、継承、[[ダイナミックバインディング]]など、今日のオブジェクト指向プログラミングには不可欠である重要な概念を導入した。{{sfn|Holmevik|1994}}
==== カプセル化 ====
Simulaはまた、プログラミングにおける{{仮リンク|データ保全|en|data security}}を考慮して設計されたものでもあった。プログラミングのデータ保全のために[[参照カウント]]による検出プロセスが実装されたのに加え、最終手段として[[ガベージコレクション|ガベージコレクタ]]が[[主記憶装置]](メモリ)内の使用されていないオブジェクトを削除するようになっていた。しかし、データオブジェクトの概念は1965年には既に確立されていたものの、プライベートやパブリックといった[[変数 (プログラミング)|変数]]の[[スコープ (プログラミング)|スコープ]]のレベルによるデータのカプセル化については、アクセスする手続きもまた隠蔽できなければならなかったため、Simulaでは実装されなかった。{{sfn|Dahl|2004}}
互いに関連するデータとメソッドをまとめてクラスとし、必要なデータとメソッドのみを外部公開し、それ以外をクラス内に隠蔽する機能をカプセル化と呼ぶ。外部公開されたデータとメソッドはクラス外からの直接アクセスが可能である。内部隠蔽されたデータとメソッドはクラス外からアクセスされないことが保証されこれは{{仮リンク|情報隠蔽|en|information hiding}}と呼ばれる。同クラス所属のメソッドを通してのデータの閲覧と変更はそのデータの抽象化を意味することになりこれは{{仮リンク|Data Abstraction|en|Abstraction (computer science)|label=データ抽象}}と呼ばれる。この二つがカプセル化の要点である。データ抽象を実装するための仕組みでもある[[This (プログラミング)|this参照]]については後節で述べられる。データ閲覧用メソッドはゲッター、データ変更用メソッドはセッターと呼ばれる。データとメソッドの外部公開範囲を、無制限・任意クラスグループ・派生クラスグループの三段階に分けて定義する機能は[[アクセスコントロール]]と呼ばれる。


初期の段階では、Simulaはプログラミング言語[[ALGOL]] 60のための手続きパッケージとされていた。しかし、ALGOLによる制約に不満を感じた研究者たちは、UNIVAC ALGOL 60コンパイラを使用した本格的なプログラミング言語としてSimulaを開発することにした。ダールとニゴールは1965年から1966年にかけてSimulaの普及に尽力し、スウェーデン、ドイツ、[[ソビエト連邦]]などでSimulaの使用が増加した。1968年には、[[バロース B5000]]上で広く利用されるようになり、後には[[ウラル・コンピュータ|URAL-16コンピュータ]]上にも実装された。1966年、ダールとニゴールはSimulaの[[コンパイラ]]を書いた。彼らは、{{仮リンク|SIMSCRIPT|en|SIMSCRIPT}} (自由形式の英語的な汎用シミュレーション言語)を実装に用いて、[[アントニー・ホーア]]のレコード・クラス概念を取り入れることに熱心に取り組んだが、彼らは、一般化されたプロセスの概念として、レコード・クラスの属性を保持する層と、接頭辞 (prefix) の系列を保持する層の二層構造とする方式に辿り着いた。
==== 継承 ====
接頭辞の系列を通じて、プロセスは先行する定義を参照し、それらの属性を追加することができる。このようにしてSimulaは、クラスとサブクラスの階層を導入し、これらのクラスからオブジェクトを生成することを可能にする方法を導入することとなった。{{sfn|Nygaard|Dahl|1978}}
既存クラスのデータ/メソッド構成に任意のデータ/メソッド構成を付け足して、既存構成+新規構成の新しいクラスを定義する機能を継承と呼ぶ。その差分プログラミング目的の継承よりも、既存構成に抽象メソッドを置いて新規構成にその実体メソッドを置くというオーバーライド目的の継承の方が要点にされている。新規構成ではなく実装内容を付け足していくための継承である。既存クラスは基底クラス、親クラス、スーパークラスなどと呼ばれ、新しいクラスは派生クラス、子クラス、サブクラスなどと呼ばれる。抽象メソッドを持つクラスは抽象クラスと呼ばれる。継承できるクラスが一つに限られている単一継承を採用している言語と、継承できるクラスの数に制限がない多重継承を採用している言語に分かれている。抽象メソッドのみで構成される純粋抽象クラスの継承は、インターフェースの{{仮リンク|実装継承|en|Inheritance_(object-oriented_programming)}}と呼ばれて抽象化目的の継承になる。


1972年には[[System/360|IBM System/360]]および[[System/370|IBM System/370]]の[[IBMメインフレーム]]用にSimula 67コンパイラが完成{{sfn|Holmevik|1994}}。同年、フランスの[[CII 10070]]および[[CII Iris]] 80[[メインフレーム]]用のSimula 67コンパイラが無償で提供された。1974年には、Simulaユーザー会は23カ国のメンバーを有するまでになっていた。1975年初頭、[[PDP-10|DECsystem-10]]メインフレームファミリー用のSimula 67コンパイラが無償でリリースされ、同年8月までにDECsystem-10のSimula 67コンパイラは28サイトにインストールされた (そのうちの22サイトは北米)。オブジェクト指向のプログラミング言語としてSimulaは、貨物港における船舶と積載貨物の動きを調査・改善するための研究のような、物理モデリングの研究に携わる研究者に主に利用されていた{{sfn|Holmevik|1994}}。
==== ポリモーフィズム ====
異なる種類のクラスに同一の操作インターフェースを持たせる機能をポリモーフィズム(多態性)と呼ぶ。これはクラスの継承関係を利用して、コンパイル時のメソッド名から呼び出されるプロセス内容を実行時に決定するという仕組みを指す。その実装は{{仮リンク|仮想関数(OOP)|en|Virtual function|label=仮想関数}}と呼ばれており、クラスベースOOPのポリモーフィズムはイコール仮想関数となっている。仮想関数はスーパークラスの抽象メソッドの呼び出しを、それを[[オーバーライド]]したサブクラスの実体メソッドの呼び出しにつなげる機能である。抽象メソッドとオーバーライド機能については後節で述べる。ポリモーフィスムの要点は、同じメソッド名からその実行時に対応した異なる処理内容を呼び出せるようにすることである。


1970年代、[[パロアルト研究所|Xerox パロアルト研究所(PARC)]]において、[[アラン・ケイ]]、[[ダン・インガルス]]、[[アデル・ゴールドバーグ]]らによって、プログラミング言語[[Smalltalk]]の最初のバージョンが開発された。Smaltalk-72はプログラミング環境を含み、[[動的型付け]]であり、当初は[[コンパイラ|コンパイル]]してからの実行ではなく[[インタプリタ]]実行であった。Smalltalkは、言語レベルでのオブジェクト指向の適用と、グラフィカルな開発環境で注目されたが、Smalltalkが様々なバージョンを経て成長するにつれ、この言語への関心も高まっていった{{sfn|Meyer|2009}}。
=== コンポジションとデリゲーション ===
SmalltalkはSimula 67で導入されたアイデアの影響を受けてはいるものの、クラスを動的に生成・変更できるなど、完全に動的なシステムとして設計された{{sfn|Kay|1993}}。
コンポジション(合成)とデリゲーション(委譲)は、継承の原型的仕組みであり、別の言い方をすると合成+委譲を最適化した機能が継承である。継承は[[is-a]]構造の委譲、合成は[[has-a]]構造の委譲と読み替える事ができる。合成とは、クラスに特定処理の委譲先となる部品クラスを複数持たせた構造であり、合成クラスがデータ/メソッドを要求されて自身が未所持の場合は、対応可能な部品クラスを選択して委譲するという仕組みである。その要求判別と選択過程を自動化したのが継承であり、部品クラスを親クラスに置き換えて暗黙の委譲先にしたものである。しかしその暗黙委譲は実際に参照されるデータ/メソッドの把握を困難にするという欠点も明らかになったので、合成の価値が再認識されるようになった。既存構成に新規構成を付け足していく差分プログラミング目的では、継承よりも合成を用いる方がよいと考えられている。

1970年代、Smalltalkは[[LISP#LISPの歴史|Lispコミュニティ]]に影響を与え、Lispコミュニティは、[[Lispマシン]]を通じて開発者に紹介されたオブジェクトベースの技術を取り入れた。Lispの様々な拡張機能(LOOPS や{{仮リンク|Flavors|en|Flavors (programming language)}}などが導入した[[多重継承]]や[[Mixin]])の試みは、最終的に[[関数型プログラミング]]とオブジェクト指向プログラミングを統合し、{{仮リンク|メタオブジェクト・プロトコル|en|Metaobject protocol}}による拡張を可能にした[[Common Lisp Object System|Common Lispのオブジェクト指向システム]] (CLOS) へとつながった。
1980年代には、メモリ上のオブジェクトをハードウェアでサポートするプロセッサ・アーキテクチャを設計する試みがいくつか行われたが、[[Intel iAPX 432]]や[[リン (企業)|Linn Smart]]、{{仮リンク|Rekursiv|en|Rekursiv}}など、いずれも商業的に成功しなかった。

1981年、ゴールドバーグは[[バイト (雑誌)|Byte Magazine]] 8月号のSmalltalk特集号で、Smalltalkとオブジェクト指向プログラミングをより多くの人々に紹介した。
1986年、[[Association for Computing Machinery|ACM]]が主催する第一回[[OOPSLA]]が開催され、予想に反して1,000人が参加した。1980年代半ばには、[[ITT (企業)|ITT]]でSmalltalkを使っていた[[ブラッド・コックス]]によって[[Objective-C]]が開発され、博士論文でSimulaを扱っていた[[ビャーネ・ストロヴストルップ]]よってオブジェクト指向の[[C++]]が作られた{{sfn|Meyer|2009}}。
1985年には、[[バートランド・メイヤー]]も[[Eiffel]]の最初の設計を行った。ソフトウェアの品質に焦点を当てたEiffelは、純粋なオブジェクト指向プログラミング言語であり、ソフトウェアのライフサイクル全体をサポートする記法をもつ。メイヤーは、ソフトウェア工学とコンピュータサイエンスの少数の重要なアイデアに基づいたEiffelでのソフトウェア開発手法を{{仮リンク|オブジェクト指向入門|en|Object-Oriented Software Construction}}で解説している。Eiffelでは、メイヤーが開発した信頼性担保の機構である[[契約プログラミング]]が、開発手法と言語の双方に不可欠な要素となっている。

[[File:Tiobeindex.png|thumb|350px|[[:en:TIOBE index|TIOBE]] [[:en:Measuring programming language popularity|プログラミング言語の人気ランキング]]の2002年から2018年のグラフ。2000年代のオブジェクト指向言語[[Java]] (青)と[[手続き型プログラミング]]言語[[C言語|C]] (黒)の首位争いの様子]]
1990年代前半から半ばにかけて、オブジェクト指向プログラミングは、その技術をサポートするプログラミング言語が広く普及したことにより、[[プログラミングパラダイム]]として主要なものとなった。その中には、[[Microsoft Visual FoxPro|Visual FoxPro]] 3.0<ref group="注">1995年6月 Visual FoxPro 3.0, FoxPro は手続き型言語からオブジェクト指向言語へと進化した。Visual [[FoxPro]] 3.0では、データベースコンテナ、シームレスなクライアント/サーバー機能、ActiveXのサポート、OLEオートメーションとヌルのサポートが導入された。[http://www.foxprohistory.org/foxprotimeline.htm#summary_of_fox_releases Summary of Fox releases]</ref><ref>FoxProの歴史: [http://www.foxprohistory.org/tableofcontents.htm Foxprohistory.org]</ref><ref>1995年のVisual FoxPro 3.0 レビュー/ガイド: [http://www.dfpug.de/loseblattsammlung/migration/whitepapers/vfp_rg.htm DFpug.de]</ref>、[[C++]]<ref>{{Cite book|url=https://books.google.com/books?id=MHmqfSBTXsAC&pg=PA16|title=Object Oriented Programming with C++, 1E|isbn=978-81-259-2532-3|last1=Khurana|first1=Rohit|date=1 November 2009}}</ref>、[[Delphi]]<ref>マイナビTECH+: Delphiがトップ20位から脱落: 「Delphiは2001年6月にトップ20位入りを果たし、2000年代初頭には最も人気のある統合開発環境として広く使用されていた。」[https://news.mynavi.jp/techplus/article/20200306-988782/]</ref>などがある。
その勢力は、オブジェクト指向プログラミング技術に支えられた[[グラフィカルユーザインタフェース]]の人気向上と共に高まった。動的なGUIライブラリとOOP言語が密接に連携している例としては、Smalltalkを規範にしたCのオブジェクト指向の動的メッセージング拡張である[[Objective-C]]で書かれた[[macOS]]の[[Cocoa (API)|Cocoa]]フレームワークなどが挙げられる。また、OOPツールキットの存在は、[[イベント駆動型プログラミング]]の人気を高めることにも繋がった(ただし、この概念はOOPに限定されるものではない)。
[[チューリッヒ工科大学]]では、[[ニクラウス・ヴィルト]]らが、[[抽象化_(計算機科学)#データ抽象化|データ抽象化]]や{{仮リンク|モジュール化プログラミング|en|Modular programming}}などの研究を行っていた (ただし、これらは1960年代以前にも一般的に使われてはいた)。
1978年に発表された[[Modula-2]]にはこの2つが盛り込まれており、その後に発表された[[Oberon]]では、オブジェクト指向やクラスなどに対する独自のアプローチが盛り込まれている<ref name=ETH>{{Cite report |last=Wirth |first=Niklaus |title=From Modula to Oberon and the programming language Oberon |series=ETH Technical Reports D-INFK |volume=Band 82 |publisher=Wiley |url=https://doi.org/10.3929/ethz-a-005363226}}</ref>。

オブジェクト指向の機能は、[[Ada]]、[[BASIC]]、[[Fortran]]、[[Pascal]]、[[COBOL]]など、既存の多くの言語に追加されていったが、しかし、設計当初にこれらの機能を想定していなかった言語に追加した場合、コードの互換性や保守性には問題が生じることが多かった。

最近では、主としてオブジェクト指向でありながら、手続き型プログラミングの方法論にも対応した言語が数多く登場している。そのような言語としては、[[Python]]や[[Ruby]]がある。最近の商業的なオブジェクト指向言語で最も重要なものには、[[サン・マイクロシステムズ]]社が開発した[[Java]]や、Microsoftの[[.NET Framework|.NET]]プラットフォーム用に設計された[[C Sharp|C#]]、[[Visual Basic .NET]] (VB.NET) が挙げられる。
これら二つのフレームワークは、実装を抽象化することによるOOP使用の利点をそれぞれの方法で示している。VB.NETとC#間では言語間継承をサポートしており、一方の言語で定義されたクラスが他方の言語で定義されたクラスをサブクラス化することができる<ref>共通型システム|Microsoft Docs [https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/common-type-system]</ref>。

== OOPLの特徴 ==
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクト指向プログラミング言語 ('''OOPL''') では、オブジェクトを使用するが、言語仕様でOOP対応を謳っていても、関連する技術や構造のすべてが言語機能により直接サポートされているわけではない。以下に挙げる特徴は、特に言及されている例外を除いて、クラス指向やオブジェクト指向の傾向が強いとされる言語 (あるいはOOPをサポートする[[マルチパラダイムプログラミング言語]])に共通すると考えられるものである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->

=== 非OOPLとの共通点 ===<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
; [[変数 (プログラミング)|変数]]: [[整数型]]や英数字の[[キャラクタ (コンピュータ)|文字]]のような形式化された少数の組み込み[[データ型]]の情報、または、[[文字列]]、[[リスト (抽象データ型)|リスト]]、[[ハッシュテーブル]]などの[[データ構造]]に、組み込み型もしくは、[[ポインタ (プログラミング)|ポインタ]]が格納されたものを結果として格納することができる。
; 手続き(関数、メソッド、[[サブルーチン]]とも呼ばれる): 入力を受け取り、出力を生成し、データを操作する。近年の言語には、[[制御構造#ループ|ループ]]や[[if文|条件構文]]のような[[構造化プログラミング]]の構成要素が含まれる。

[[:en:Modular programming|モジュラープログラミング]]サポートでは、手続きをファイルやモジュールにまとめて整理する機能がある。モジュールは[[名前空間]]を持つため、あるモジュールの識別子が、他のモジュールの同名の手続きや変数と衝突することを避けることができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->

=== クラスとオブジェクト ===
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクト指向プログラミング(OOP)をサポートする言語は、コードの再利用と拡張性のために、典型的には、[[クラスベース|クラス]]または[[プロトタイプベース|プロトタイプ]]の形で[[継承 (プログラミング)|継承]]を使用する。クラスを使用するものは、主に二つの概念をサポートする。
; [[クラス (コンピュータ)|クラス]]
: 与えられた型やクラスのオブジェクトのデータ形式やそれらを利用可能な手続きの定義であり、また、データや手続き (クラスメソッドとも呼ばれる)そのものを含む場合もある。つまり、クラスは、メンバーとなるデータや手続きを含むものである。
; [[オブジェクト (プログラミング)|オブジェクト]]
: クラスのインスタンス
<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->

<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクトは、システムが扱おうとする(多くは現実世界の)対象を表現したものである。例えば、描画アプリケーションにおける「円」・「四角」・「メニュー」などのオブジェクトや、オンラインショッピングシステムにおける「ショッピングカート」・「顧客」・「商品」などのオブジェクトがある<ref>{{cite book|last=Booch|first=Grady|title=Software Engineering with Ada|year=1986|publisher=Addison Wesley|isbn=978-0-8053-0608-8|page=220|url=https://en.wikiquote.org/wiki/Grady_Booch|quote=Perhaps the greatest strength of an object-oriented approach to development is that it offers a mechanism that captures a model of the real world.}}</ref>。
オブジェクトは、ファイルのオープンを表すオブジェクトや、[[米国慣用単位]]から[[メートル法]]に変換するサービスを提供するオブジェクトのように、より抽象的なエンティティを表すこともある。

{{Quote box
|quote = オブジェクト指向プログラミングとは、単なるクラスやオブジェクトではなく、データフィールドやメソッドを含んだオブジェクト (データ構造)を中心としたプログラミングパラダイム全般のことです。クラスを使って、関係のないメソッドをまとめて整理する——これがオブジェクト指向の本質ではないことを理解しましょう。
|author = Junade Ali
|source = ''Mastering PHP Design Patterns''{{harv|Ali|2016|p=11}}
|width = 50%
|align = right
}}

各々のオブジェクトは、特定のクラスの[[インスタンス]]と呼ばれる (例えば、<code>name</code>フィールドに <code>"Mary"</code>が設定されているオブジェクトは、クラス<code>Employee</code>のインスタンスとなる)。OOPの手続きは[[メソッド (計算機科学)|メソッド]]と呼ばれ、変数は、[[フィールド (計算機科学)|フィールド]]、メンバー、属性、プロパティとも呼ばれる。関連して、以下のような用語がある
; [[クラス変数]]
: クラス自体に属する。変数をクラス全体に唯一のものとして所有する。
; [[インスタンス変数]]または属性
: 各々のオブジェクトに属する。データはオブジェクトごとに所有する。
; [[メンバ変数]]
: 特定のクラスで定義されるクラス変数とインスタンス変数の両方を指す。
; [[クラスメソッド]]
: クラス自体に属する。クラス変数へのアクセスのみ有し、手続き呼び出しからの入力のみ受け付ける。
; [[インスタンスメソッド]]
: 各々のオブジェクトに対して、呼び出された特定のオブジェクトのインスタンス変数、入力、およびクラス変数にアクセスできる。

オブジェクトは、複雑な内部構造を持った変数のようにアクセスされるが、多くの言語で実質的には[[ポインタ (プログラミング)|ポインタ]]でありインスタンス (ヒープやスタック内のメモリ上オブジェクト)への参照として機能する。オブジェクトは、内部コードと外部コードを分離を可能とする[[抽象化 (計算機科学)|抽象化]]の層を提供する。外部のコードは、特定の入力引数の組み合わせで特定のインスタンスメソッドを呼び出したり、インスタンス変数を読み込んだり、インスタンス変数に書き込んだりすることで、オブジェクトを使用することができる。オブジェクトは、[[コンストラクタ]]と呼ばれるクラス内の特定メソッドを呼び出すことで生成される。プログラムは実行中に、それぞれ独立して操作することが可能な同じクラスのインスタンスを多数作成することができる。これは、同じ手続きを異なるデータセットで簡便に利用する方法となる。

クラスを使用するOOPを[[クラスベース]]・プログラミングと呼ぶことがあるが、[[プロトタイプベース]]・プログラミングではクラスを使用しないのが一般的である。そのため、'''オブジェクト'''と'''インスタンス'''という概念の定義は、それぞれで大きく異なるが類似した用語が用いられている。

言語によっては、[[トレイト]]や[[mixin]]のような概念を用いてクラスやオブジェクトを構成することが可能である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->

=== クラスベース対プロトタイプベース ===
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[クラスベース|クラスベースの言語]]では、予め''クラス''が定義され、そのクラスに基づいて''オブジェクト''がインスタンス化される。例えば、''apple''と''orange''という2つのオブジェクトが、''Fruit''というクラスからインスタンス化された場合、それらは本質的には果物であり、同じように取り扱えることの保証がされる。

[[プロトタイプベース|プロトタイプベースの言語]]では、''オブジェクト''が主要な実体である。''クラス''は存在しない。オブジェクトの''プロトタイプ''とは、あるオブジェクトからリンクされている別のオブジェクトに過ぎない。すべてのオブジェクトは一つの''プロトタイプ''リンクを持つ (一つのみ)。新しいオブジェクトは、プロトタイプとして選ばれた既存のオブジェクトに基づいて作成することができる。''fruit''オブジェクトが存在し、''apple''と''orange''の両方が''fruit''をプロトタイプとしている場合、2つの異なるオブジェクト''apple''と''orange''を果物と考えることができる。''fruit''「クラス」という概念は明示的には存在しないが、同じプロトタイプを共有するオブジェクトの[[同値類|同値クラス]]としては存在する。''プロトタイプ''の属性やメソッドは、このプロトタイプで定義された同値クラスのすべてのオブジェクトから[[委譲]]先とされる。オブジェクト固有の属性やメソッドは、同値クラスの他のオブジェクトに共有されない場合がある。例えば、属性''sugar_content''は''apple''には予期せず存在しない場合がある。プロトタイプで実装できるのは[[:en:Multiple_inheritance#Single_inheritance|単一継承]]のみである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->


=== 動的ディスパッチとメッセージパッシング ===
=== 動的ディスパッチとメッセージパッシング ===
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
動的ディスパッチはポリモーフィズムの原型的仕組みであり、継承構造上での[[This (プログラミング)|this]]参照によるシングルディスパッチを最適化した機能が仮想関数である。動的ディスパッチはコンパイル時のメソッド名から呼び出されるメソッド内容が実行時に決定される仕組み全般を指す用語であり、メソッド名を基軸にして各引数の型によってプロセスが選択分岐される仕組みを意味するシングルディスパッチと[[多重ディスパッチ]]を包括している。一つの引数の型がプロセス選択に影響するのはシングル、二つ以上なら多重になる。
メソッドの呼び出しに応じて実行する手続きのコードを選択するのは、外在するコードではなく、オブジェクトの責任である。典型的には、オブジェクトに関連付けられたテーブルから実行時にメソッドを検索するが、この機能は[[:en:Dynamic dispatch|動的ディスパッチ]]として知られており、[[抽象データ型]] (またはモジュール)において、すべてのインスタンスの操作が静的に実装されているのとは対照的である。呼び出しの変化が、呼び出されたオブジェクトの単一の型にのみには依らない場合 (つまり複数のオブジェクトがメソッド選択に関与する場合)、[[多重ディスパッチ]]と呼ばれる。


メソッド呼び出しは、[[メッセージ (コンピュータ)|メッセージパッシング]]とも呼ばれる。これは、メソッド呼び出しを、ディスパッチのためにオブジェクトに渡されるメッセージ (メソッドの名前とその入力引数)として概念化したものである。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
メッセージパッシングでは、引数の型に加えてメソッド名も実行時に解釈される要素にされておりそれはセレクタと呼ばれる。<code>object selector: param</code>ような書式でオブジェクトの共通窓口となるメッセージレシーバーにセレクタと引数のメッセージが送られる。また、<code>object.call(method_name, param)</code>のような書式でオブジェクトの共通窓口関数をコールするのもメッセージパッシングと呼ばれる。これは[[Remote Procedure Call|遠隔手続きコール]]や[[Object Request Broker|オブジェクト要求ブローカー]]で用いられており分散オブジェクトの標準的なインターフェース機構になっている。関数名も実行時に解釈されるという特徴を指してメッセージパッシングと呼ぶ。よく用いられるセレクタ対応プロセスを自動選択化してコンパイル時最適化した仕組みがメソッドになり、これは関数名をコンパイル時決定する関数呼び出しと同類になった。


=== インターフェース ===
=== カプセル化 ===
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[カプセル化]]とは、オブジェクト指向プログラミングにおいて、データとそのデータを操作する関数を結び付け、両者を外部からの干渉や誤用から守ることである。データのカプセル化は、OOPの重要な概念である{{仮リンク|情報隠蔽|en|Information hiding|redirect=1}}にも通じる。
インターフェースはカプセル化を更に突き詰めた仕組みであり、データ抽象とメソッド抽象と情報隠蔽を合わせて実現する最もOOPらしい機能と言える。インターフェースは抽象メソッドのみで構成されている純粋抽象クラスである。ゲッター、セッター、プロセスになる各抽象メソッドの実装内容は利用者側から隠されて実行時のその都度に決定される。


クラスがメソッドを通じてのみオブジェクトの内部データへのアクセスを許可し、それ以外の呼び出しコードにアクセスを許可しない場合、これはカプセル化として知られる強力な抽象化、または情報隠蔽の形態である。いくつかの言語 (Javaなど)では、クラスがアクセス制限を明示的に行うことができる。例えば、内部データであることを<code>private</code>というキーワードで指定し、クラス外のコードが使用することを意図したメソッドを<code>public</code>というキーワードで指定することができる。また、メソッドはpublic、private、または<code>protected</code> (同クラスとそのサブクラスからのアクセスは許可するが、異なるクラスのオブジェクトからのアクセスは許可しない)のように中間のアクセスレベルとすることもできる。また他の言語 (Pythonなど)では、アクセス制限は、命名法などの慣例によってのみ強制される (例えば、<code>private</code>のメソッドは[[アンダースコア]]で始まる名前を持つ、など)。カプセル化することで、外部のコードがオブジェクトの内部動作に関与してしまうことを防ぐことができ、[[リファクタリング (プログラミング)|リファクタリング]]を容易にする。例えば、クラスの設計者は、外部のコードは変更することなく、そのクラスのオブジェクト内部のデータ表現を変更することができる (公開されているメソッドの呼び出しが同じように動作する限りにおいて)。また、特定のデータに関連するすべてのコードを同じクラスに配置することで、他のプログラマが理解しやすいように整理することもできる。カプセル化は、[[結合度|疎結合]]を促進する技術である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
=== プロトタイプとオブジェクト ===
[[クラスベース]]のクラスと実体化とインスタンスは、[[プロトタイプベース]]ではプロトタイプと複製とオブジェクトに置き換わる。プロトタイプとオブジェクトの大きな特徴は、プロパティとメソッドを自由に付け替えできることでありこれは[[動的束縛|動的バインディング]]とも呼ばれ、そのプロパティとメソッドの構成による型は[[ダックタイピング]]で判別される。この特徴は同時に[[ポリモーフィズム]]になる。その用法は[[関数オブジェクト]]と変数オブジェクト(値オブジェクト)に大別され、前者は[[二階述語論理]]、後者は[[高階述語論理]]の表現体になり、それ自体が[[メタデータ|メタ]]視点から抽象化されたオブジェクトには[[カプセル化]]という概念は必要でなくなる。[[継承 (プログラミング)|継承]]の意味合いも異なりクラスベースの基底と派生は、プロトタイプベースではプロパティ/メソッド構成のアタッチ候補とそのアタッチ先に置き換わる。アタッチ候補は親クラスや[[トレイト]]などと呼ばれる。アタッチ候補は事実上の[[委譲|デリゲーション]]先でもある。トレイトは多重継承前提でありこれは[[ミックスイン]]と呼ばれ、構造的型付けでその実装継承が判別される。


=== コンポジション、継承、委譲 ===
[[プロトタイプベース]]は動的な[[関数型プログラミング]]に似た性質になっているが、オブジェクトの柔軟な用法に対しての一定の枠組みが必要であるとも考えられるようになり、静的な[[クラス (コンピュータ)|クラス]]定義が積極的に導入されるようになった。現状のプロトタイプベースは元来の[[The Art of the Metaobject Protocol|メタオブジェクト]]構想から離れて、関数型とOOPのハイブリッドのようなパラダイムに落ち着いている。
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->オブジェクトは、そのインスタンス変数に他のオブジェクトを含めることができ、これを[[:en:object composition|オブジェクトコンポジション]]と呼ぶ。例えば、"従業員"クラスのオブジェクトは、"名前" や "役職"といった自身のインスタンス変数に加えて、"住所"クラスのオブジェクトを (直接またはポインタを介して)含むことができる。
オブジェクトコンポジションは、"has-a" の関係を表現するために使用できる。例えば、すべての従業員は住所を持っているので、すべての"従業員"オブジェクトは、"住所"オブジェクトを格納する場所 (オブジェクトに直接埋め込まれていることも、ポインターで指定された別の場所に格納されることもある)にアクセスできる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->


<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->クラスをサポートする言語は、大抵は[[継承 (プログラミング)|継承]]をサポートしている。継承とは、クラスを「○○は△△である」という関係("is-a-type-of")の階層に配置することであるが、例えば、<code>Employee</code> クラスは <code>Person</code> クラスを継承する場合、親クラスで利用できるデータやメソッドは、子クラスでも同じ名前で利用可能である。また、<code>Person</code> クラスは、<code>first_name</code> と <code>last_name</code> という変数を <code>make_full_name()</code> というメソッドで定義した場合、これらの定義は<code>Employee</code>クラスでも利用可能である。加えて、<code>Employee</code>クラスには変数 <code>position</code> と <code>salary</code> を追加することもできる。この手法では、同じ手続きやデータ定義を簡単に再利用できるだけでなく、現実世界の関係を直感的に反映できる可能性を広げる。開発者は、データベースのテーブルやプログラミングのサブルーチンを扱うのではなく、開発アプリケーションのユーザーがより精通しているドメインのオブジェクトを扱うことができる<ref>{{cite book|last=Jacobsen|first=Ivar|title=Object Oriented Software Engineering|year=1992|publisher=Addison-Wesley ACM Press|isbn=978-0-201-54435-0|pages=[https://archive.org/details/objectorientedso00jaco/page/43 43–69]|author2=Magnus Christerson|author3=Patrik Jonsson|author4=Gunnar Overgaard|url=https://archive.org/details/objectorientedso00jaco/page/43}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
== 歴史 ==
1954年に初の[[高水準言語]]・[[FORTRAN]]が登場すると、開発効率の劇的な向上と共にソフトウェア要求度も自然と高まりを見せてプログラム規模の急速な拡大が始まった。それに対応するために肥大化したメインルーチンを[[サブルーチン]]に分割する手法と、[[スパゲティプログラム|スパゲティ化]]した[[Goto文|goto命令]]を[[制御構造|制御構造文]]に置き換える手法が編み出され、これらは1960年に公開された言語「[[ALGOL|ALGOL60]]」で形式化された。当時のALGOLは[[アルゴリズム]]記述の一つの模範形と見なされたが、それと並行して北欧を中心にした計算機科学者たちはより大局的な観点によるプログラム開発技法の研究を進めていた。


<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->サブクラスはスーパークラスで定義されたメソッドをオーバーライドできる。言語よっては[[:en:Multiple inheritance|多重継承]]が可能だが、多重継承ではオーバーライドの解決は複雑になる可能性がある。また、言語によっては[[mixin]]を特別にサポートしているものもあるが、多重継承をサポートする言語では、mixinは単に ''is-a-type-of'' の関係を表すことのないクラスの一つである。mixinは典型的には、同一のメソッドを複数のクラスに追加するために使われる。例えば、共通の親クラスを持たない<code>FileReader</code>クラスと<code>WebPageScraper</code>クラスに、<code>unicode_to_ascii()</code>というメソッドを持つ<code>UnicodeConversionMixin</code>クラスを含ませる(mixinする)ことにより共通のメソッドを提供することができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
=== 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]]([[CAD]]と[[GUI]]の元祖)の設計内にあるObjectが先例であった。Simula67コンパイラはまず[[UNIVAC I|UNIVAC]]上で運用され、翌年から汎用機[[バロース B5000|バロースB5500]]などでも稼働されて北欧、ドイツ、ソ連の各研究機関へと広まり、1972年には[[IBMメインフレーム|IBM汎用機]][[System/360]]などにも導入されて北米全土にも広まった。その主な用途は物理シミュレーションであった。{{Quotation|''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.''
<br>([[Sketchpad]]、[[Simula]]、[[アーパネット|ARPAネット]]、[[バロース B5000|バロースB5000]]、それと専攻していた生物学と数学に影響されて僕はプログラミングアーキテクチャを思索していた)|Alan Kay}}
=== 構造化プログラミングの提唱(1969 - 75) ===
[[Simula]]の普及と前後して1960年代半ばになると、プログラム規模の際限ない肥大化に伴う開発現場の負担増大が顕著になり、いわゆる[[ソフトウェア危機]]問題が計算機科学分野全般で取り沙汰されるようになった。その解決に取り組んだ計算機科学者[[エドガー・ダイクストラ]]は、1969年のNATOソフトウェア工学会議で「[[構造化プログラミング]]」という論文を発表し[[トップダウン設計とボトムアップ設計|トップダウン設計]]、段階的な[[抽象化 (計算機科学)|抽象化]]、階層的な[[モジュール化]]、共同詳細化(抽象データ構造と抽象ステートメントのjoint)といった構造化手法を提唱した。ダイクストラの言う構造化とは開発効率を高めるための[[分割統治法]]を意味していた。なおこの構造化プログラミングは後に曲解されて[[制御構造|制御構造文]]を中心にした解釈の方で世間に広まり定着している。共同詳細化は抽象データ構造を専用ステートメントを通して扱うという概念である。これはSimulaの手続きを通してクラス内の変数にアクセスするという仕組みをモチーフにしていた。段階的な抽象化と階層的なモジュール化は時系列的にも、SIMSCRIPTの段階的データ構造と、Simura67の継承による階層的クラス構造を模倣したものであった。[[エドガー・ダイクストラ|ダイクストラ]]、[[アントニー・ホーア|ホーア]]、[[オルヨハン・ダール|ダール]]の三名は1972年に『構造化プログラミング』と題した共著を上梓していることから互いの研鑽関係が証明されている。その階層的プログラム構造という章の中でダールは、Simulaの目指した設計を更に明らかにした。{{Quotation|''I'm not against types, but I don't know of any type systems that aren't a complete pain, so I still like dynamic typing.''
<br>(僕は型アンチではないが、全くうんざりしない型システムも知らない、だからまだ動的型付けを好んでいる)|Alan Kay}}1974年に[[MIT]]の計算機科学者[[バーバラ・リスコフ]]は「[[抽象データ型]]」というプログラム概念を提唱し、ダイクストラが提示したモジュールの共同詳細化を、その振る舞いによって[[セマンティクス|意味内容]]が定義される抽象データという考え方でより明解に形式化した。一方、1970年に構造化言語[[Pascal]]を開発していた計算機科学者[[ニクラウス・ヴィルト]]は、ダイクストラによる共著出版後の1975年にモジュール化言語[[Modula-2|Modula]]を提示してモジューラプログラミングというパラダイムを生み出している。このようにいささか奇妙ではあるが、Simulaのクラスとオブジェクトというプログラム概念は、巷で言われる構造化からモジュール化へといった進化の流れとは関係なく、しかもその前段階においてさながら彗星のように生まれたパラダイムであった。


<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->[[抽象型|抽象クラス]]は、オブジェクトへインスタンス化することはできない。インスタンス化できる他の具象クラスが継承するためにのみ存在する。Javaでは、<code>[[final (Java)|final]]</code>キーワードを用いて、クラスがサブクラス化されるのを防止できる。
=== Smalltalkとオブジェクト指向の誕生(1972 - 81) ===
Simula発のProcessとクラスの示した可能性は、[[パロアルト研究所]]の計算機科学者[[アラン・ケイ]]によるオブジェクト重視と「メッセージング」という考え方のヒントになった。ケイはプログラム内のあらゆる要素をオブジェクトとして扱い、オブジェクトはメッセージの送受信でコミュニケーションするという独特のプログラム理論を提唱した。それには関数適用風の書式を用いたオブジェクト同士の多種多様な[[委譲|デリゲーション]]と、プログラムコードとしても解釈できるデータ列を送信してそれを評価(''eval'')することで新たなデータを導出できるなどのアイディアが盛り込まれていた。オブジェクトが送るか受け取ったメッセージは任意のタイミングで評価できるので非同期通信や単方向通信をも可能にしていた。この発想の背景には[[LISP]]の影響があった。オブジェクトとメッセージングの構想に基づいて開発された「[[Smalltalk]]」はプログラミング言語と[[GUI]]運用環境を併せたものとなり、1972年に[[データゼネラルNova]]上での1000行程度のBASICを使った試作(概念実証)を経て、翌1973年に新開発された[[Alto|ゼロックスAlto]]上で本格稼働された。Smalltalkの設計を説明するためにケイが考案した「[[オブジェクト指向]]」という用語はここで初めて発信された。またケイのメッセージング構想は[[MIT]]の計算機科学者[[カール・ヒューイット]]に能動的な[[プロセス代数]]を意識させて、1973年発表の[[アクターモデル]]のヒントにもなっている。しかしデリゲーションの多用とデータ列が常にコード候補として扱われる処理系は、当時のコンピュータには負荷が大きく実用的な速度を得られないという問題にすぐ直面した。Smalltalk-74(新たに開発された[[BitBLT]]を使った高速描画版Smalltalk-72)からSmalltalk-76の過程で、やむなくメッセージは(多くの場合)関数の動的コールに、メソッドはパターンマッチ処理から単なる関数へ置き換えられるなど構想時の柔軟さが失われるほど最適化された。また、ケイの留保した継承機構も導入されてオブジェクトは抽象データ型の性格も有するようになった。{{Quotation|''Smalltalk is not only NOT its syntax or the class library, it is not even about classes. I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea.The big idea is "messaging"...''
<br>(Smalltalkはその構文やライブラリやクラスをも関心にしていないという事だけではない。多くの人の関心を小さなアイディアに向かせたことから、僕はオブジェクトという用語を昔作り出したことを残念に思っている。大切なのはメッセージングなんだ。)|Alan Kay}}1980年のSmalltalk-80は、元々はメッセージを重視していたケイを自嘲させるほど同期的で双方向的で手続き的なオブジェクト指向へと変貌していた。それでも動的ディスパッチと[[委譲]]でオブジェクトを連携させるスタイルは画期的であり、1994年に発表される[[デザインパターン (ソフトウェア)|デザインパターン]]の模範にもされている。1981年に当時の著名なマイコン専門誌『[[Byte (magazine)|BYTE]]』がSmalltalkとケイ提唱のオブジェクト指向を紹介して世間の注目を集める契機になったが、ケイの思惑に反して技術的関心を集めたのはクラス機構の方であった。オブジェクト指向は知名度を得るのと同時に、Simula発の[[クラス (コンピュータ)|クラス]]とそれを理論面から形式化した[[抽象データ型]]を中心に解釈されるようになり、それらの考案者がケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。


[[:en:Composition over inheritance|Composition over inheritance]]の方針は、継承の代わりに合成を使って has-a 関係を実装することを提唱している。例えば、EmployeeクラスはPersonクラスを継承する代わりに、各Employeeオブジェクトの内部にPersonオブジェクトを含めることで、仮にPersonクラスが公開された属性やメソッドを多数持っていても、外部のコードからは隠せるようにする。また、[[Go (プログラミング言語)|Go]]のように、継承を全くサポートしていない言語も存在する。
=== C++の開発と普及(1979 - 88) ===
[[Simula]]を研究対象にしていた[[ベル研究所|AT&Tベル研究所]]の計算機科学者[[ビャーネ・ストロヴストルップ]]は、1979年からクラス付きC言語の開発に取り組み、1983年に「[[C++]]」を公開した。C++で実装された[[クラス (コンピュータ)|クラス]]は、Simula譲りの[[継承 (プログラミング)|継承]]と仮想関数に加えて、[[レキシカルスコープ]]の概念をクラス構造に応用した[[アクセスコントロール]]を備えていた。C++で確立されたアクセスコントロールはカプセル化の元になったがコードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(''not just'')オブジェクト指向言語であると明言している。1986年にソフトウェア技術者[[バートランド・メイヤー]]が開発した「[[Eiffel]]」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性、手続き、関数の三種構成で、手続きで属性を変更し関数で属性を参照するという形式に限定されており、これは抽象データ型の[[セマンティクス|振る舞い意味論]]に沿った実装であった。アクセスコントロールはモジューラプログラミングの情報隠蔽に沿った方式になり、仮想関数機能は延期手続き/関数として実装された。{{Quotation|''I made up the term ‘object-oriented’, and I can tell you I didn’t have C++ in mind.''
<br />(僕はオブジェクト指向という言葉を作ったけど、C++(のような言語)は考えていなかった)|Alan Kay}}1986年から[[Association for Computing Machinery|ACM]]が[[OOPSLA|オブジェクト指向会議]](OOPSLA)を年度開催し、そのプログラミング言語セクションでは[[抽象データ型]]の流れを汲む[[クラス (コンピュータ)|クラス]]・パラダイムが主要テーマにされ、それを標準化するための数々のトピックが議題に上げられている。[[モジュール性]]、情報隠蔽、[[抽象化 (計算機科学)|抽象化]]、再利用性、[[継承 (プログラミング)|階層構造]]、複合構成、実行時多態、[[動的束縛]]、[[総称型]]、[[ガベージコレクション|自動メモリ管理]]といったものがそうであり、参画した識者たちによる寄稿、出版、講演を通して世間にも広められた。そうした潮流の中で[[ビャーネ・ストロヴストルップ|ストロヴストルップ]]はデータ抽象の重要性を訴え、[[バーバラ・リスコフ|リスコフ]]は[[上位概念、下位概念、同位概念および同一概念|基底と派生]]に分けたデータ抽象の[[リスコフの置換原則|階層構造の連結関係]]について提言した。[[契約による設計]]を提唱する[[バートランド・メイヤー|メイヤー]]が1988年に刊行した『オブジェクト指向ソフトウェア構築』は名著とされ、Eiffelを現行の模範形とする声も多く上がった。ただしこれは学術寄りの意見でもあったようで、世間のプログラマの間では厳格なEiffelよりも柔軟で融通の利くC++の人気の方が高まっていた。他方でオブジェクト指向本来の原点であるメッセージ・メタファに忠実であろうとする動きもあり、1984年に開発された「[[Objective-C]]」はSmalltalkをモデルにしてそれを平易化した言語であった。そのメッセージレシーバーは静的なメソッド機構優先の動的ディスパッチ機構という方式で実装された。メッセージレシーバの仕組みは[[遠隔手続き呼出し]]/[[Object Request Broker|オブジェクト要求ブローカー]]の実装に適していたので[[分散システム]]とオブジェクト指向の親和性を認識させることになった。


[[開放/閉鎖原則]]は、クラスやメソッドは「拡張に対しては開放的であるが、変更に対しては閉鎖的であるべき」という原則を提唱している。
=== プロトタイプベースの黎明(1979 - 91) ===
[[Smalltalk]]のEverythingIsAnObject思想をより具体化した[[プロトタイプベース]]のルーツになっている。また、[[パロアルト研究所]]でSmalltalkの方言として制作されていた「[[Self]]」が1987年に初回稼働され1990年に一般公開された。Selfにも導入されていたメタオブジェクト相当の仕様が、後に[[プロトタイプベース]]と呼ばれるオブジェクト指向スタイルに発展した。


[[委譲]]もまた、継承の代わりに利用できる言語機能である。<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->
=== コンポーネントとネットワーク(1989 - 97) ===
ネットワーク技術の発展に連れて、データとメソッドの複合体であるオブジェクトの概念は、[[分散システム]]構築のための基礎要素としての適性を特に見出される事になり、[[IBM|IBM社]]、[[アップル (企業)|アップル社]]、[[サン・マイクロシステムズ|サン社]]などが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]]」といったオブジェクト指向スクリプト言語がリリースされ、従来の[[クラスベース]]に対する[[プロトタイプベース]]という新しいオブジェクト指向スタイルを定着させている。1994年の[[ギャング・オブ・フォー (情報工学)|GOF]][[デザインパターン (ソフトウェア)|デザインパターン]]の発表と、1997年に[[Object Management Group|OMG]]が標準[[モデリング言語]]として採用した[[統一モデリング言語|UML]]は、オブジェクト指向プログラミングの標準化を促進させた。{{Quotation|''... there were two main paths that were catalysed by Simula. The early one (just by accident) was the bio/net non-data-procedure route that I took. The other one, which came a little later as an object of study was abstract data types, and this got much more play.''<br>(Simulaを触媒にした二本の道があった。最初の一本はバイオネットな非データ手法で僕が選んだ方。少し遅れたもう一本は抽象データ型、こっちの方がずっと賑わっている。)|Alan Kay}}


=== ポリモーフィズム ===
== 代表的なオブジェクト指向言語 ==
<!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->[[サブタイピング (計算機科学)|サブタイピング]] ([[ポリモーフィズム]]の一形態)では、呼び出すコードが、サポートされている階層のどのクラスを操作しているのか (親クラスなのかその子孫なのか)という詳細には関知しないことが可能である。一方、継承階層内のオブジェクト間では、同じ操作名でも挙動が異なる場合がある。
オブジェクト指向言語は、[[抽象データ型]]に準拠した[[クラスベース]]、{{仮リンク|メタオブジェクトプロトコル|en|Metaobject|label=}}を採用した[[プロトタイプベース]]、[[Smalltalk]]を規範にした[[メッセージパッシング|メッセージング]]ベースの三タイプに分類されるのが一般的である。[[クラスベース]]では「C++」「Java」「C#」が代表的である。[[プロトタイプベース]]では「Python」「JavaScript」「Ruby」が有名である。[[メッセージパッシング|メッセージング]]ベースでは「Smalltalk」「Objective-C」「Self」などがある。言語仕様の中でオブジェクト指向の存在感が比較的高い代表的なプログラミング言語は以下の通りである。
[[ファイル:History of object-oriented programming languages.svg|境界|中央|フレームなし]]
;[[Simula|Simula 67]] 1967年
:1962年に公開された[[Simula]]の後継バージョンであり、[[クラス (コンピュータ)|クラス]]のプログラム概念を導入した最初の言語である。物理モデルを解析するシミュレーション制作用に開発されたもので、クラスをメモリに展開したオブジェクトはその観測対象要素になった。Simulaのクラスは、一つのローカル変数構造と複数のプロシージャをまとめたミニモジュールと言えるものであったが、継承と仮想関数という先進的な設計を備えていた事でオブジェクト指向言語の草分けと見なされるようになった。[[クラスベース]]の源流である。
;[[Smalltalk]] 1972年
:[[メッセージパッシング|メッセージング]]のプログラム概念を導入した最初の言語。数値、真偽値、文字列から変数、コードブロック、メタデータまでのあらゆるプログラム要素をオブジェクトとするアイディアを編み出した最初の言語であり、[[プロトタイプベース]]の源流にもなった。オブジェクト指向という言葉はSmalltalkの言語設計を説明する中で生み出された。オブジェクトにメッセージを送るという書式であらゆるプロセスを表現することが目標にされている。動的ディスパッチと[[ダイナミックバインディング|動的バインディング]]相当の機構である[[メッセージ転送|メッセージレシーバー]]と[[委譲|デリゲーション]]は、後年の[[デザインパターン (ソフトウェア)|デザインパターン]]のモデルにもされた。GUI運用環境に統合された専用のランタイム環境上で動作させる設計も模範にされ、これは後に[[仮想マシン]]や[[仮想実行システム]]と呼ばれるものになる。
;[[C++]] 1983年
:[[C言語]]に[[クラスベース]]のオブジェクト指向を追加したもの。Simulaの影響を受けている。[[静的型付け]]の[[クラス (コンピュータ)|クラス]]が備えられてカプセル化、継承、多態性の三仕様を実装している。カプセル化ではアクセス修飾子とフレンド指定子の双方から可視性を定義できる。継承は多重継承、オーバーライド制約用の継承可視性、[[菱形継承問題]]解決用の[[仮想継承]]も導入されている。多態性は[[仮想関数]]によるサブタイプ多相、[[テンプレート (プログラミング)|テンプレートクラス&関数]]によるパラメトリック多相、[[多重定義|関数&演算子オーバーロード]]によるアドホック多相が導入されている。元がC言語であるため、オブジェクト指向から逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。
;[[Objective-C]] 1984年
:[[C言語]]に[[メッセージパッシング|メッセージング]]ベースのオブジェクト指向を追加したもの。こちらはSmalltalkの影響を受けており、それに準じた[[メッセージパッシング]]の書式が備えられた。メッセージを受け取るクラスの定義による[[静的型付け]]と共に、メッセージを[[委譲]]するオブジェクトの実行時決定による[[動的型付け]]も設けられている。オブジェクト指向的にはC++よりも正統と見なされた。[[制御構造|制御構造文]]が追加され、メッセージ構文も平易化されており、Smalltalkよりも扱いやすくなった。
;[[Object Pascal]] 1986年
:[[Pascal]]にクラスベースのオブジェクト指向を追加したもの。当初はモジュールのデータ隠蔽的なカプセル化、単一継承、仮想関数による多態性という基本的なものだった。静的型付け重視である。[[ニクラウス・ヴィルト|ヴィルト]]監修の[[アップル (企業)|アップル社]]による初回バージョンを土台にして様々な企業団体による派生版が公開されており、その特徴と機能追加も様々である。
;[[Eiffel]] 1986年
:[[C++]]の柔軟性と融通性とは正反対のオブジェクト指向言語。[[クラスベース]]で[[静的型付け]]重視である。[[契約プログラミング|契約による設計]]に基づく[[表明|アサーション]]の挿入でクラスの状態および演算用の引数と返り値を細かくチェックできる。[[例外処理]]も備えられている。クラスメンバ(フィーチャー)はデータ、アクセッサ、ミューテイタの三種限定で[[多重定義|オーバーロード]]はできない。カプセル化の可視性は自身に依存するクラス(クライアント)を定義する形で決められる。多重継承可能であり、クラス間の繋がりを[[仮想継承]]機能、各種[[オーバーライド]]指定子、名前衝突を解決するリネーミング機能などで綿密に設定できる。多態性は[[仮想関数|延期関数/手続き]](サブタイプ多相)と[[ジェネリックプログラミング|ジェネリシティ]](パラメトリック多相)である。[[ガーベジコレクション]]機能が初めて導入されたオブジェクト指向言語でもある。
;[[Self]] 1987年
:[[メッセージパッシング|メッセージング]]ベースのオブジェクト指向言語でSmalltalkの方言として開発された。それ故にプロトタイプからプロトタイプを派生させ、またインスタンスを複製してそれにプロパティとメソッドを[[ダイナミックバインディング|動的バインディング]]できるというメタオブジェクトプロトコルも忠実に実装された。[[プロトタイプベース]]というパラダイムはこのSelfから認知されるようになった。[[動的型付け]]重視である。Smalltalkと同様に専用のランタイム環境上で実行され、GUI運用環境の構築も目標にしていた。Selfのランタイム環境は[[実行時コンパイラ]]機能を初めて実装したことで知られており画期的な処理速度を実現している。この技術は[[Java仮想マシン]]の土台になった。
;[[Common Lisp]]([[CLOS]]) 1988年(ANSI規格化は1994年)
:[[クラスベース]]のオブジェクト指向。メソッド記述の関数呼び出し形式への統合、[[多重ディスパッチ]]、クラスの動的な再定義等を特徴とする。
;[[Python]] 1994年
:[[プロトタイプベース]]のオブジェクト指向スクリプト言語。[[基本データ型]]や[[コンテナ (データ型)|コレクション型]]などよく使われるデータ要素を全て組み込みのオブジェクトにしている。それらは[[手続き型プログラミング|手続き型]]スタイルでも気軽に扱える。コレクション型を扱うのに適した[[関数型プログラミング|関数型]]構文も導入されている。関数/変数のオブジェクトは自由にプロパティとメソッドを付け足し付け替え可能である。オブジェクトは[[ダックタイピング]]で型判別されるので変数/関数の型宣言と型注釈は撤廃されている。ゆえに[[動的な型付け|動的型付け]]重視である。Pythonのプロトタイプはクラスと呼ばれている。多重継承可能であり親クラス要素のサーチ順序はC3線形化で解決されている。多態性は事実上メソッドの動的バインディングになっている。カプセル化は軽視されている。後期バージョンで型ヒントが追加され、それに伴い[[ジェネリクス]]も導入された。
;[[Java]] 1995年
:[[C++]]をモデルにしつつ堅牢性とセキュリティを重視した[[クラスベース]]のオブジェクト指向言語。静的型付け重視である。パッケージ中心のカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性と、基本に忠実なクラスベースである。C++風の[[ポインタ (プログラミング)|ポインタ]]と値型インスタンスは除外されて参照型インスタンスに統一した。[[例外処理]]を整備し[[演算子オーバーロード]]を除外した。オブジェクト指向と[[マルチスレッド]]の調和が図られ、[[ソフトウェアコンポーネント|コンポーネント指向]]による動的クラスローディングの存在感が高められている。クラスメタデータを操作できる[[リフレクション (情報工学)|リフレクション]]は初期から採用された。中期から[[ジェネリクス]](パラメトリック多相)と[[アノテーション|メタアノテーション]](アドホック多相)が導入され、ラムダ式と関数型インターフェースを軸にした[[関数型言語|関数型構文]]も採用された。[[仮想マシン]]上で実行される。[[仮想マシン]]と[[ガーベジコレクション]]の技術は比較的高度と見なされている。
;[[Delphi]] 1995年
:[[Object Pascal]]を発展させたもの。それと同様にこちらも基本に忠実なクラスベースで静的型付け重視であった。当初はデータベース操作プログラム開発を主な用途にして公開された。クラスとレコード([[構造体]])に同等の比重が置かれていた。一時期Javaの対抗馬になった。
;[[Ruby]] 1996年
:[[Python]]を意識して開発されたオブジェクト指向スクリプト言語。[[Smalltalk]]を一つの理想にしてより万人向けの言語を目指し、動的型付けを重視している。日本で誕生してグローバル化したプログラミング言語である。[[LISP]]とSmalltalkのメタプログラミング的なオブジェクト指向から、Pythonと[[JavaScript]]のプロトタイプベースなオブジェクト指向までのスタイルとコーディング手法を幅広く取り入れている。
;[[JavaScript]] 1996年
:[[プロトタイプベース]]のオブジェクト指向スクリプト言語。型宣言と型注釈を撤廃して[[ダックタイピング]]する[[動的な型付け|動的型付け]]重視である。すべてをオブジェクトにする[[Smalltalk]]の思想に忠実な言語であり、[[Python]]と似ているがそれよりも[[プロトタイプベース]]性質と[[関数型プログラミング]]性質を追求している。定数、変数、構造体、関数などが全て同性質のオブジェクトにされており、プロパティとメソッドを自由に付け足したり付け替えできるようにデザインされている。関数オブジェクトの構築と用い方がプログラミング上のキーポイントになっており、[[クロージャ]]、[[高階関数]]、[[第一級関数]]、デコレータ、[[パイプライン処理|パイプライン]]といった多種多様な働き方とその組み合わせを柔軟に表現できる。[[ウェブアプリケーション|WEBアプリケーション]]開発を主な用途にして公開されたのでオブジェクトは[[GUI]]パーツの構築にも最適化されている。[[ECMAScript]]として標準化されており、2015年版からは[[クラスベース]]向けの構文もサポートするようになった。
;[[C Sharp|C#]] 2000年
:[[Java]]を強く意識してマイクロソフト社が開発したクラスベースのオブジェクト指向言語。Javaよりも[[マルチパラダイムプログラミング言語|マルチパラダイム]]の性質が強化されている。C++譲りの柔軟性と融通的を残しながら様々な[[糖衣構文]]サポートも加えてコーディング上の利便性がより高められている。[[マルチスレッド]]仕様も整備されている。アドホック多相では拡張メソッド、インデクサ、演算子オーバーロードなどを備えている。パラメトリック多相では[[共変性と反変性 (計算機科学)|共変/反変]]も扱える[[ジェネリクス]]を備えている。サブタイプ多相はクラスは単一継承でインターフェースは多重実装と基本通りである。[[関数型言語|関数型構文]]も整備されており、特にメソッド参照機能であるデリゲートの有用性が高められている。デリゲートは[[イベント駆動型プログラミング|イベント駆動構文]]の平易な表現も可能にしている。基本は[[静的型付け]]であるが、動的束縛型と[[ダックタイピング]]による[[動的型付け]]の存在感が高められているので漸進的型付けの言語と見なされている。[[.NET Framework]]([[共通言語基盤]]=仮想実行システム)上で実行される。
;[[Scala]] 2003年
:[[クラスベース]]のオブジェクト指向と[[関数型プログラミング]]を融合させた言語。[[クラス (コンピュータ)|クラス]]機構と関数型の[[型システム]]に同等の比重が置かれており静的型付け重視である。[[ミックスイン]]相当の[[トレイト]]と、[[共変性と反変性 (計算機科学)|共変/反変]]および抽象タイプメンバを扱える[[ジェネリクス]]を連携させた多態性が重視されておりオブジェクトを様々に[[派生型|派生型付け]]できる。シングルトンオブジェクトの役割が形式化されて従来のクラス静的メンバの新解釈にも用いられている。専用の定義書式により[[イミュータブル]]なオブジェクトが重視されている。上述の派生型付けスタイルとオブジェクト引数の[[逆写像|抽出]]構文と[[パターンマッチング|パターンマッチング式]]の併用連鎖計算は[[モナド (プログラミング)|モナド]]を彷彿とさせて独特の関数型スタイルを表現できる。[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。
;[[Kotlin]] 2011年
:静的型付けの[[クラスベース]]のオブジェクト指向であるが、[[手続き型プログラミング]]に回帰しており、クラス枠外の関数とグローバル変数の存在感が高められている。クラスはpublicアクセスとfinal継承がデフォルトにされて、カプセル化と継承が公然と軽視されている。これによりインスタンスは手続き型の関数の対象値としての役割が強められ、その操作をサポートする関数型構文も導入されている。仮想関数と抽象クラスによる多態性は標準通りである。[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。
;[[TypeScript]] 2012年
:[[JavaScript]]を強く意識してマイクロソフト社が開発したオブジェクト指向スクリプト言語。JavaScriptのプログラムを静的型付けで補完した言語である。[[クラスベース]]向けの構文と、[[関数型プログラミング]]の[[型システム]]のスタイルが加えられている。特に後者の性質が強調されている事から静的型付け重視である。継承構造によるサブタイプ多相はほぼ除外されており、[[ジェネリクス]]と型アノテーションでオブジェクトを扱うというパラメトリック多相とアドホック多相を重視するデザインになっている。オブジェクト指向ではあるが関数型の性格が強めである。
;[[Swift (プログラミング言語)|Swift]] 2014年
:[[Objective-C]]を発展させたものであるが、メッセージ構文は破棄されており、クラスベースのオブジェクト指向になっている。オブジェクトの[[イミュータブル|イミュータブル性]]重視の構文が採用されている。プロテクト可視性の削除によってクラスの縦並びの継承は軽視されており、プロトコルの横並びの多重実装を重視している。プロトコルは[[インタフェース (抽象型)|インターフェース]]と[[ミックスイン]]の中間的機能であり、インスタンスはプロトコルを基準にして型分類され、また抽象化される。プロトコルと[[ジェネリクス]]の連携による多態性が重視されている。モジュールの動的ローディングは不透明型の仕組みで補完されている。[[静的型付け]]重視である。


例えば、Circle型とSquare型のオブジェクトが、Shapeという共通のクラスから派生している場合、Shapeの各型のDraw関数は、それぞれの描画に必要な機能を実装しているが、呼び出しのコードは、描画されるShapeが特定の型であるかどうかには無関心でいられる。
== 用語と解説 ==
;[[クラス (コンピュータ)|クラス]]
:(''class'')の仕組みを中心にしたオブジェクト指向を[[クラスベース]]と言う。クラスはデータとメソッドをまとめたものであり、[[プログラム意味論|操作的意味論]]を付加された静的[[構造体|レコード]]とも解釈される。クラスはインスタンスのひな型であり、インスタンスはクラスを実例化(量化)したものである。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化は[[This (プログラミング)|this参照]]の仕組みの実装およびデータとメソッドの可視性を指定できる機能である。継承は自身のスーパークラスを指定できる機能である。多態性は[[オーバーライド]]と[[仮想関数テーブル]]を処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。
;プロトタイプ
:(''prototype'')の仕組みを中心にしたオブジェクト指向を[[プロトタイプベース]]と言う。プロトタイプとは識別名&中間参照ペアの集合体を指す。この集合体は一般にフレームと呼ばれる。識別名&中間参照ペアの割り当て箇所は一般にスロットと呼ばれる。スロットにはデータとメソッドの識別名&中間参照ペアが代入されるので、プロトタイプはクラスと同様にデータとメソッドをまとめたものになる。プロトタイプは言語によってはクラスと呼ばれている。プログラマはシステムが提供する基底プロトタイプに、自由にデータとメソッドを付け足して任意の派生プロトタイプを作成できる。プロトタイプは「型」相当であり、それを複製する方式で生成されるインスタンスは「値」相当である。データとメソッドはその参照にインスタンスを必要とするものと、しないものに分かれる。前者はインスタンスメンバ、後者は静的メンバに相当するものである。インスタンスにも自由にデータとメソッドを付け足すことができる。インスタンスはそのプロトタイプへの参照を保持しており、プロトタイプはその親プロトタイプへの参照を保持している。これは継承相当の機能になっている。インスタンスへの自由なメンバ付け替えは多態性相当の機能になっている。ただしプロトタイプは動的な[[関数型言語]]由来の仕様なのでクラスベースOOPの三大要素とはまた違った視点から眺める必要がある。
;[[メッセージ (コンピュータ)|メッセージ]]
:オブジェクト指向で言われるメッセージ(''message'')とは、オブジェクトの呼び出し側と呼び出される側の間であらゆる事柄が実行時に決められる仕組み全般を指す用語である。関数名の解釈、引数構成、返り値構成、関数名対応プロセス所有の是非、委譲先、同期/非同期タイミングといったものが実行時のその都度に決められる。実行時に解釈される関数名文字列はセレクタと呼ばれる。これは無制限に柔軟な仕様の関数呼び出しと考えてもよく、その実装方法の明確な定義は不可能である。代表例を挙げると分散オブジェクトや分散システムで用いられているメッセージパッシングは、関数名も実行時に解釈できる引数要素にした仕組みである。Smalltalk指向の言語に導入されているメッセージレシーバーとメソッドミッシングでは、特定のセレクタに対応するプロセスをコンパイル時定義できるようにして自動実行時選択されるようになっており、プロセス未定義セレクタだけが実行時解釈される仕組みになっている。このコンパイル時定義のセレクタプロセスをメソッドと呼んだ。OOPでメンバ関数をわざわざメソッドと呼ぶのはメッセージパッシング由来のこうした経緯からである。アラン・ケイはメッセージング(''messaging'')というより遠大な構想を持っていた。
;[[インスタンス]]
:(''instance'')はクラスベースではクラスを実例化(量化)したものであり、実装レベルで言うとデータ群と仮想関数テーブルをメモリ上に展開したものになる。プロトタイプベースではプロトタイプを複製する方式で生成されたオブジェクトを指す。実装レベルで言うとメモリ上に展開された識別名&中間参照ペアの動的配列になる。
;[[フィールド (計算機科学)|データメンバ]]
:(''data member'')はクラスに属する変数。データ(''data'')とも略称される。言語によってフィールド(分節)、プロパティ(特性)、アトリビュート(属性)、メンバ変数と呼ばれる。データは、クラスデータとインスタンスデータに分かれる。クラスデータは静的データとも呼ばれる。その中で定数化されたものはクラス[[定数 (プログラミング)|定数]]と呼ばれる。クラスデータはクラス名の名前空間でスコープされたグローバル変数と同じものであり、プログラム開始時から終了時まで確保される。インスタンスデータはインスタンス生成時にメモリ上に確保されるものであり、その破棄時に消滅する。インスタンスデータの参照にはそのthis参照が必要である。プロトタイプベースでは、プロトタイプで定義されたデータでそのアクセスにインスタンス(self)を必要としないものが静的データになる。
;[[メソッド (計算機科学)|メソッド]]
:(''method'')はクラスに属する関数。言語によってはメンバ関数、メンバ手続きとも呼ばれる。データの参照に特化したものはゲッター(''getter'')アクセッサ(''accessor'')と呼ばれる。データの変更に特化したものはセッター(''setter'')ミューテイタ(''mutator'')と呼ばれる。メソッドは、クラスメソッドとインスタンスメソッドに分かれる。クラスメソッドは静的メソッドとも呼ばれる。クラスメソッドはクラス名の名前空間でスコープされたグローバル関数と同じものである。インスタンスメソッドを呼び出すにはそのthis参照が必要である。プロトタイプベースでは、プロトタイプで定義されたメソッドでそのアクセスにインスタンス(self)を必要としないものが静的メソッドになる。
;[[コンストラクタ]]
:(''constructor'')はインスタンス生成時に呼び出されるそのクラスのメソッドである。インスタンスデータを任意の値で初期化するためのものであるが、その他の初期化コードも記述できる。プロトタイプベースではシステム提供プロトタイプが保持する生成用メソッドまたは生成用のグローバル関数がコンストラクタ相当になる。
;[[デストラクタ]]
:(''destructor'')はインスタンス破棄時に呼び出されるそのクラスのメソッドである。インスタンス破棄の影響を解決する任意の後始末コードを記述できる。インスタンスの破棄は占有メモリの解放を意味する。なお、ガーベジコレクタ実装言語ではファイナライザになっている事がある。プログラマが呼び出すデストラクタの方はその終了がメモリ解放に直結しているのに対し、ガーベジコレクタが呼び出すファイナライザの方はそうではない。
;[[This (プログラミング)|this参照]]
:(''this'')は言語によっては「self」や「me」とも呼ばれる。<code>instance.method()</code>の書式で呼び出されたメソッド内で、そのインスタンスのメンバを暗黙アクセスできるようにするための仕組みである。<code>instance</code>のアドレスが暗黙引数として<code>method</code>に渡されて、その<code>method</code>内で<code>this</code>となる。インスタンスのメンバアクセス時はこの<code>this</code>が自動的に付加され、例えば<code>data</code>がシステム内では<code>this.data</code>のように変換されている。メソッドはインスタンスの実体化元(量化元)クラスで定義されているものである。これは、データにメソッドを付属させるカプセル化を実現するための仕組みである。this参照に対するsuper参照(''super'')は、サブクラスのインスタンスメソッド内で用いられるものであり、直上スーパークラスのデータ/メソッドにアクセスするための参照である。オーバーライドやドミナンスを無視してスーパクラスのメンバを呼び出すための仕組みである。
;アクセスコントロール
:(''access control'')は、カプセル化の情報隠蔽に基づいた機能であり、クラス内のデータとメソッドの可視性を決定する。可視性とはそれにアクセス(参照/変更)できる範囲を意味する。これにはレキシカルスコープ基準とクライアント基準の二通りがあるが、前者の方が一般的である。広く使われているレキシカルスコープ基準の可視性は、プライベート、プロテクト、パブリックの三種が基本である。プライベートは同クラス内のメンバからのみ、プロテクトは同クラス内と派生クラス内のメンバからのみ、パブリックはどこからでもアクセス可能である。クライアント基準の可視性は、自身メンバへのアクセスを許可するクライアントクラス(フレンドクラス)を定義する方法で決められる。そのクライアントの許可は同時にその派生クラスの許可も兼ねている事が多く、継承によるクラス群の一括定義を可能にする。
;コピーコンストラクタ
:(''copy constructor'')は、メソッドの引数に対する値インスタンスの値渡しの時に呼び出されるコンストラクタである。値渡しはインスタンス内容全体のメモリコピーであり、基本データ型では特に問題は生じないが、そうでないクラスのインスタンスでは例えばあるリソースへの参照を保持している場合に好ましくない保持重複が発生する事になる。呼び出されたコピーコンストラクタは値インスタンスを受け取り、単純コピーが許されない部分に任意の処理を施して生成した値インスタンスのコピーを引数へと渡す。
;[[オーバーロード]]
:(''overloading'')は、同じメソッド名(返り値の型+メソッド名)にそれぞれ異なるパラメータリスト(引数欄)を付けたものを列挙してメソッドを多重定義する仕組みを指す。[[演算子]]もオーバーロード対象であり、[[単項演算子]]なら一つの引数の型、[[二項演算子]]なら二つの引数の型を多重定義することで演算対象の値の型ごとに計算内容をカスタマイズできる。任意個数の引数を多重定義できる( )演算子は、[[クロージャ]]または[[関数オブジェクト]]の表現に用いられる。


これもまた、クラス階層からコードを引き離して単純化し、強力な[[関心の分離]]を可能にする抽象化の一種である。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
;[[オーバーライド]]
:(''method overriding'')は、基底クラスで定義されたメソッド名義の呼び出しを、派生クラスで実装されたメソッド内容の実行につなげる機能である。これは基底メソッドを派生メソッドで上書きすると形容される。オーバーライドされた基底メソッドの内容はスルーされて派生メソッドの内容が実行される。メソッドシグネチャ(返り値の型+メソッド名+各引数の型と個数)が完全一致している基底側が派生側でオーバーライドされる。オーバーライド指定は、基底側のメソッドをvirtualやabstractで修飾する方式と、派生側のメソッドをoverrideやredefineで修飾する方式がある。前者では基底側でオーバーライド可否の定義が固定されるのに対して、後者では派生側で再定義できる。finalで修飾されたメソッドは再定義不可のオーバーライドの拒絶になる。オーバーライドメソッドの呼び出しは、基底クラスの型に代入された派生クラスのインスタンスで行われる。オーバーライドによって呼び出される内容が多相化されたメソッドは[[仮想関数]]と呼ばれる。[[仮想関数テーブル]](''virtual method table'')はその多相化のための仕組みであり、メソッドシグネチャとメソッド内容アドレスがマッピングされている。
;ドミナンス
:(''dominance'')は言語によってハイディング(''hiding'')マスキング(''masking'')とも呼ばれる。継承による階層的クラス構造において、サブクラスのメンバがスーパークラスの同名のメンバを隠していることを指す。親クラスのAメソッドを子クラスが同名Aメソッドでドミナンスした場合、子の型で参照しているインスタンスはそこでAのサーチが止まって子Aが呼び出される。ただし親の型で参照すれば親Aを呼び出せる。オーバーライドと異なり、参照する型でインスタンスの振る舞いを変えるための単純な仕組みでもある。
;[[仮想継承]]
:(''virtual inheritance'')は、多重継承での[[菱形継承問題]]を回避するための仕組みである。菱形継承問題とは共にAクラスを親とするBクラスとCクラスの双方を継承した場合に、その継承構造上でAクラスが二つ重なって存在することになる不具合である。仮想継承では専用のテーブルが用意されて、そこでクラス名が参照アドレスにマッピングされる。BクラスからのAクラスと、CクラスからのAクラスは共に同じ参照アドレスをマッピングするのでAクラスはひとつにまとめられる事になる。同時に一度辿ったクラスは省略される事にもなる。
;MRO
:メソッド解決順序(''method resolution order'')は、多重継承時の親クラスの巡回順序を定義するものである。参照されたメソッドが自クラスにない場合はその親クラスを巡回してサーチされる。メソッドはクラスメンバと読み替えてもよい。これは[[深さ優先探索|深さ優先検索]](''deep-first'')と[[幅優先探索|幅優先検索]](''breadth-first'')に分かれるが、オブジェクトの構造概念から深さ優先の方が自然とされている。従って一般的な多重継承では深さ優先検索が用いられて親クラスの重複は仮想継承で解決されている。しかし詳細は割愛するが、仮想継承部分の巡回順序に不自然さを指摘する意見もあったので、これを解決するために深さ優先と幅優先をミックスしたC3線形化(''C3 linearization'')というメソッド解決順序が考案された。C3線形化では親クラスの重複部分に対してのみ幅優先検索を適用することで、仮想継承を用いることなく菱形継承問題も自然に解決されている。
;[[抽象クラス]]
:(''abstract class'')は、全部または一部のメソッドが抽象化されているクラスを意味する。即ち抽象メソッドを持つクラスである。抽象メソッド(''abstract method'')は、メソッドシグネチャ(返り値の型+メソッド名+各引数の型と個数)だけが定義されてコード内容が省略されているメソッドである。抽象クラスはインスタンス化できないので継承専用になる。抽象メソッドはそのサブクラスの方でコード内容が実装されてオーバーライドされる。


=== オープンな再帰 === <!-- ここから [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
{{型システム}}
[[:en:This_(computer_programming)#Open_recursion|オープンな再帰]]<ref>{{Cite book|和書|title=型システム入門 |publisher=オーム社 |year=2013 |page=185}} 18.10 selfを介したオープンな再帰</ref>をサポートする言語では、オブジェクトのメソッドは同じオブジェクト上の他のメソッドや自分自身を呼び出すことができる。通常は<code>this</code>や<code>self</code>と呼ばれる特別な変数やキーワードを使用して呼び出しをするのが一般的であるが、この変数は「[[束縛_(コンピュータ)#名前束縛|遅延結合]]」であり、あるクラスで定義されたメソッドが、そのサブクラスで後から定義された別のメソッドを呼び出すことができる。<!-- ここまで [[en:Object-oriented programming]] oldid=1051733225 の翻訳 -->
;[[インタフェース (抽象型)|インターフェース]]
:(''interface'')はプログラム概念と機能名の双方を指す用語である。言語によってはプロトコルと言われる。抽象メソッドと実体メソッドをメンバにする純粋抽象〜半抽象クラスを意味する。一般的にデータはメンバにされない。クラスの振る舞い側面を抜き出した抽象体である。クラスによるインターフェースの継承は実装と呼ばれる。多重実装可が普通である。ミックスインとの違いは、抽象階層に焦点が当てられている事であり、直下の実装オブジェクトを共通の振る舞い側面でまとめることがその役割である。インターフェースは自身の[[下位概念]]である実装継承オブジェクトをグループ化できる。{{仮リンク|記名的型付け|en|Nominal type system|label=}}に準拠しているのでインターフェースの実装の明記が振る舞い側面の識別基準になる。インターフェースは抽象メソッド主体なので多重継承時のメンバ名の重複はあまり問題にならない。共通の実装メソッドに集約されるからである。インターフェースは非インスタンス対象である。
;[[ミックスイン]]
:(''mixin'')はインターフェースに似たプログラム概念を指す用語である。機能名は言語によって[[トレイト]]、プロトコル、構造型(''structural type'')と言われる。抽象メソッドと実体メソッドとデータをメンバにする継承専用クラスを意味する。クラスを特徴付けるための構成パーツである。クラスによるトレイトの継承は実装と呼ばれる。多重実装可が普通である。インターフェースとの違いは、トレイトの実装階層に焦点が当てられている事であり、オブジェクトを所有メンバで特定してまとめることがその役割である。トレイトは自身の[[上位集合]]である実装継承オブジェクトをグループ化できる。{{仮リンク|構造的型付け|en|Structural type system|label=}}に準拠しているので所属メンバ構成自体がトレイト等価性の識別基準になる。これはトレイト実装を明記していなくても、そのトレイトが内包する全メンバを所持していれば同じトレイトと見なされることを意味する。トレイトは合成や交差が可能である。トレイトは多重継承時のメンバ名重複の際にその参照の優先順位に注意する必要がある。トレイトは非インスタンス対象である。
;型イントロスペクション
:''(type introspection'')は一般に実行時型チェックと呼ばれるものである。プログラマが認知できない形で[[コンパイラ]]または[[インタプリタ]]が別途実装している[[インスタンス]]の型情報を、実行時にその都度参照してインスタンスの型を判別する仕組みである。[[静的型付け]]下では専用の実行時型チェック構文(instanceofやdynamic_cast)によって型判別し、ダウンキャストなどに繋げられる。[[動的型付け]]下では変数への再代入時や関数への引数適用時にランタイムシステムが自動的に型判別し、[[多重ディスパッチ]]などに繋げられる。型イントロスペクションでは型情報のタグ識別子が判定基準になっているので{{仮リンク|記名的型付け|en|Nominal type system|label=}}の考え方に準じている。
;[[ダックタイピング]]
:''(duck typing'')は、特定のメソッド名(メソッドシグネチャ)またはプロパティ名(データ名)の識別子を持っているかどうかでインスタンスをその都度分類する仕組みである。これはその場限りの型判別と言えるものである。判別されたインスタンスは自身が持つとされたメソッドまたはプロパティを呼び出される事になる。[[動的型付け]]の機能であり、ダックタイピングでは型情報の構成内容が判定基準になっているので{{仮リンク|構造的型付け|en|Structural type system|label=}}の考え方に準じている。
;[[型推論]]
:オブジェクト指向下の型推論''(type inference'')は、型宣言ないし型注釈を省略して定義された変数の「型」が自動的に導き出される機能を指す。型はクラスと同義である。[[静的型付け]]の機能であり、コンパイラまたはインタプリタがソースコードをあらかじめ解析し、初期値の代入を始めとしたその変数の扱われ方によって型を導き出す。ここで導き出される「型」とは他の変数への代入可能性や、関数の引数への適用可能性といったあくまで等価性の基準で決められるので、プログラマが人為的な意味付けによる型定義を重視している場合は予期せぬ結果が発生することにもなる。型推論は{{仮リンク|推論的型付け|en|Inferred typing|label=}}とも呼ばれ、普通に型宣言と型注釈を用いる{{仮リンク|明示的型付け|en|Manifest typing|label=}}の対極に位置付けられるが、昨今のオブジェクト指向言語では双方を併用するのが主流になっている。


== デザインパターン ==
;[[メタクラス]]
:(''metaclass'')は{{仮リンク|メタオブジェクトプロトコル|en|Metaobject|label=}}に準拠した機能名であり、実装方式は言語毎に違いがある。メタクラスは、クラスのデータ、メソッド、スーパークラス、内部クラスなどの定義情報を記録した[[メタデータ]]である。クラスベースのメタクラス機能は、実装レベルではシステム側が用意している特別なシングルトンオブジェクトと考えた方が分かりやすい。それにはほとんどの場合システム側が提供する抽象インターフェースを通してのみアクセスできる。メタクラス内容を閲覧/変更できる機能はリフレクションと呼ばれる。プロトタイプベースでは、インスタンスの複製元であるプロトタイプまたはクラスがメタクラス機能も備えており、データとメソッドの静的な事前定義の他、実行時にも動的にデータとメソッドを付け替えできる。プロトタイプないしクラスもプログラマが自由に扱えるオブジェクトになっている。
;[[リフレクション (情報工学)|リフレクション]]
:(''reflection'')は、メタクラス内容を閲覧/変更する機能であるが、変更できる内容範囲は言語ごとに異なっている。データではデータ型、識別子、可視性が変更対象になる。メソッドではリターン型、識別子、パラメータリスト、可視性、オーバーライド指定が変更対象になる。双方の追加定義と削除もできる事がある。スーパークラスも変更できる事がある。メタクラスの変更はそのまま関連クラスと関連インスタンスにリフレクション(反映)される。ただし反映範囲はこれも言語によって異なる。
:また、実行時の文字列(char配列やString)をデータとメソッドの内部識別子として解釈できる機能もリフレクションであり、上述のメタクラス操作よりもこちらの方がよく用いられる。これは実行時の文字列データを用いてのデータ/メソッドへの動的なアクセスを可能にする。
;[[アノテーション|メタアノテーション]]
:(''metadata annotation'')はクラスに任意の情報を埋め込める機能である。情報とは文字列と数値からなるキーワード、シンボル、テキストである。プログラマが自由な形式で書き込んで随時読み取るものであるが、システムから認識される形式のものもある。実装レベルではメタクラスに書き込まれてリフレクション機能またはその[[糖衣構文]]で読み取ることになる。[[マーカーインタフェース|マーカーインターフェース]]の拡張とも見なされている。メタアノテーションはクラス単位だけでなく、言語によってはインスタンス単位やメソッド単位でも埋め込むことができる。
;メソッド拡張
:(''method extension'')は、クラス定義とは別の場所でそのクラスに対する追加メソッドを定義できる機能である。これは状況に合わせてデータ抽象の表現に幅を持たせることを目的にしている。これには数々の書式があるが代表的なのは、静的メソッドまたは静的関数の第1引数をthis修飾して、その第1引数のクラス(型)に対してその静的メソッドをインスタンスメソッドとして追加するというものである。静的メソッドはそのクラススコープ内の限定拡張にできる。静的関数はネスト関数にしてそのローカルスコープ内の限定拡張にできる。双方はグローバル用途にすることもできる。


=== 継承とBehavioral subtyping ===
;動的ディスパッチ
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->継承は[[プログラム意味論|意味論]]的には [[is-a]] の関係を作るため、サブクラスからインスタンス化されたオブジェクトは、スーパークラスからインスタンス化されたオブジェクトの代わりに、常に''安全に''使用できる、と推測するのは直感的ではあるが、この直観は、ほとんどのOOPL、特に[[イミュータブル|ミュータブル]]なオブジェクトを許可している言語では誤りである。 (ミュータブルなオブジェクトを持つ)OOPLの型検査器によって強制される[[ポリモーフィズム|部分型付け (部分型多相/サブタイピング多相)]]では、いかなる状況でも、振る舞いにおける部分型付け ([[:en:Behavioral subtyping|Behavioral subtyping]]) は保証することはできない。 Behavioral subtyping は一般に決定不能であり、プログラム (コンパイラ)では実装できない。クラスやオブジェクトの階層は、文法間違いでは検出できない使い方がされる可能性を考慮に入れて、慎重に設計する必要がある。この問題は[[リスコフの置換原則]]としても知られている。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->
:(''dynamic dispatch'')は、コンパイル時のメソッド名から呼び出されるメソッド内容が実行時に決定される仕組み全般を指す用語である。メソッドに引数を渡しての呼び出しを、オブジェクトにメッセージを発送(ディスパッチ)することになぞらえた事が由来である。発送先は実行時に選択決定されるメソッド内容を指す。メッセージは「[[This (プログラミング)|this参照]]×第1引数×第2引数..」といった[[直積集合]]で考えられているのでシングル、ダブル、マルチプルといった呼称になっている。発送先はthisおよび各引数の派生関係の組み合わせで選択される。thisの派生関係のみ影響しているものは仮想関数と呼ばれるシングルディスパッチになる。それがthisでなく引数ならばただのシングルディスパッチになる。thisまたは各引数の内の2個以上のオブジェクトの派生関係が影響しているものは[[多重ディスパッチ|マルチプルディスパッチ]]になる。その中で特にthisと先頭引数の2個が影響して先頭引数インスタンスの仮想関数がthisを引数にしているVisitor形態のものは[[ダブルディスパッチ]]と呼ばれている。
;[[動的束縛|動的バインディング]]
:(''dynamic binding'')は、識別子が参照するまたは呼び出すオブジェクト、インスタンス、メソッド、データなどのプログラム要素が、コンパイル時ではなく実行時に決められる仕組み全般を指す用語である。識別子はいわゆる変数名や関数名などを指す。


;遅延バインディ
=== GoFデザインパター ===
{{Main|デザインパターン (ソフトウェア)}}
:(''late binding'')は、識別子が参照するオブジェクトをコンパイル時に決める事前バインディング(''early binding'')の対義語であり、この場合は識別子が参照するオブジェクトを実行時に決める動的バインディングと同じ意味で用いられる。また他方では動的バインディングの中で、特に実行コードの動的ローディング機能を通して実装される方を遅延バインディングとする考え方もある。実行コードとは[[ダイナミックリンクライブラリ|DLL]]やクラスライブラリやモジュールなどを指しており、それらが内包するクラスやメソッドを専用の不透明型または動的束縛型に代入する。その呼び出しのための内部識別子はコンパイル時には存在していないことが多いので、実行時の文字列(char配列やString)を内部識別子に解釈するためのリフレクション機能が多用されることになる。


=== オブジェクト指向とデータベース ===
;[[パッケージ (Java)|パッケージ]]
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->
:(''package'')は1個以上のクラスをまとめたものである。多くなったクラスをグループ化するための仕組みである。パッケージの定義は言語ごとに異なるが、[[名前空間]](''namespace'')と同等の機能になっているケースが多い。実装レベルではパッケージ名は自動的にクラス名の接頭辞になってクラス名を差別化し、名前衝突を回避している。
{{Main|[[インピーダンスミスマッチ|オブジェクト-リレーションインピーダンスミスマッチ]]|オブジェクト関係マッピング|オブジェクトデータベース}}


OOPL と[[関係データベース管理システム]] (RDBMS) は、どちらも{{As of|2021|alt=今日}}のソフトウェアとして非常に一般的であるが、双方を接続する場合、[[関係データベース]]は、オブジェクトを直接格納しないため (ただし、今日ではこれに近しい拡張機能を持つ RDBMS も存在する)、この二つの世界を橋渡しすることが一般的な需要として擡頭した。アクセス方法やデータパターンを OOPL と RDB との間で橋渡しする際の問題は、オブジェクト-リレーションの[[インピーダンスミスマッチ]]と呼ばれている。
;[[モジュール]]
この問題に対処するためのアプローチはいくつかある。欠点のない一般的な解決策といえるものはない<ref name="RDMDBobjectmis">{{Cite web| first = Ted| last = Neward| title = The Vietnam of Computer Science| date = 26 June 2006| access-date = 2 June 2010| publisher = Interoperability Happens| url = http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx| archive-url = https://web.archive.org/web/20060704030226/http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx| archive-date = 4 July 2006| url-status = dead| df = dmy-all}}</ref>が、代表的なものとして、[[オブジェクト関係マッピング]](ORM)があり、[[Microsoft Visual FoxPro|Visual FoxPro]]などの[[統合開発環境|IDE]]言語や、Java Data Objects、[[Ruby on Rails]]の[[Active Record]]などのライブラリが存在する。
:(''module'')は1個以上のクラスをまとめたものである。ここでは[[手続き型プログラミング|手続き型]]や[[構造化プログラミング]]でのそれではなく、OOP言語で扱われているモジュール概念について説明する。ただしその定義は言語間で様々である。上述のパッケージと同等の機能にしている言語もある。ミックスインのために使われる変数と関数のメンバグループをそれにしてトレイトと同等の機能にしている言語もある。また、クラス群の動的ローディングに焦点を当てた[[ソフトウェアコンポーネント]]相当の機能にしている言語もある。この動的ローディングは遅延バインディングと同義になり、実行中プロセスへのクラス群の逐次追加を可能にしている。動的ローディング用途のモジュールでは、内包する基底クラスの詳細を明らかにしつつも、その派生クラスの種類と詳細を明らかにしていないケースが多々あるので、その派生クラスを代入するための動的束縛型は特に不透明型(''opaque type'')と呼ばれる。不透明型はもっぱら型制約と併せて用いられる。
;[[モンキーパッチ]]
:(''monkey patch'')はモジュールやスクリプトファイルなどの動的ローディングを用いて、インタプリタ実行後またはコンパイル後のソースコード内容を変化させる手法である。ソースコードに専用のフィルター処理を記述しておき、その中で任意の箇所を動的ローディングされたモジュール内のクラスや関数や変数で置き換えさせる事で、その時の配置モジュールに合わせた処理内容の変化を起こせる。モジュールを外せば専用のフィルター処理は無効になる。この置き換え(パッチ当て)は遅延バインディング相当である。ソースコードを変えなくてよいのが条件である。
;[[ジェネリクス]]
:(''generics'')は、クラスメンバの任意の「型」を総称化したままのクラス定義を可能にし、そのクラスをインスタンス化する各構文箇所で「型」の詳細を決定できるようにしたコンパイル時の静的な機能である。言語によっては[[テンプレート (プログラミング)|テンプレート]](''template'')と呼ばれる。ここでの「型」とはデータの型やメソッドの引数値/返り値/計算値の型を指している。クラス内のそれらを総称化して型変数にし、コンストラクタ呼び出し時の仮型引数に実型引数を適用すると、型変数に実型引数を当てはめたインスタンスが生成される。総称化された型を持つクラスはジェネリッククラスと呼ばれる。特定の型に依存しないクラスを汎用的に定義できるので、型が違うだけの重複コードを削減できるという利点がある。
:言語によっては、ジェネリッククラス同士を[[共変性と反変性 (計算機科学)|共変性と反変性]]による継承関係で結ぶことができる。これはジェネリッククラスに適用する実型引数の継承関係を、そのジェネリッククラス同士の継承関係にシフトする仕組みである。<code>class 猫 extends 動物</code>とすると<code>List<猫></code>は<code>List<動物></code>のサブクラスになる。共変性は実型引数の継承関係をそのままジェネリッククラスの継承関係にシフトするが、反変性ではこれを逆にする。共変性では<code>List<猫></code>は<code>List<動物></code>のサブクラスだが、反変性では<code>List<動物></code>は<code>List<猫></code>のサブクラスになる。[[共変性と反変性 (計算機科学)|共変性と反変性]]はまとめてバリアンス(''variance'')と呼ばれる事がある。
;型制約
:(''type constraint'')は、(A)ジェネリッククラスの型引数/型変数、(B)代入値の型が実行時に決められる動的束縛型の変数、(C)動的ローディング時に詳細が隠されたままの値が代入される不透明型の変数、などの宣言に用いられるものである。それぞれは制約用の基準クラスで記号修飾され、その基準クラス及びその派生型の値が代入、束縛、適用されるという宣言になる。(A)の型引数/型変数では基準クラス及びその派生クラスが適用される宣言になる。(B)の動的束縛型では基準クラス及びその派生型の値が代入される宣言になる。(C)の不透明型では基準クラス及びその詳細不明である派生型の値が代入される宣言になる。型制約は型境界(''type bound'')とも呼ばれる。これには上限と下限がある。型制約と上限型境界(''upper type bound'')は性質的に同義である。下限型境界(''lower type bound'')は、基準クラス及びその基底型の値が代入、束縛、適用されるという宣言になる。
;タイプメンバ
:(''abstract type member'')はジェネリッククラスのメンバ要素であり、ジェネリッククラス同士で型変数の内容をやり取りするための仲介要素である。Aクラスコンストラクタの型引数にBクラスを適用した際に、適切な代入定義が併記されたAクラス内のタイプメンバに、Bクラスがその内部で扱っている総称型もセットで適用できる。連想配列さながらにBクラスがキー的存在になってAクラスのタイプメンバ内容も決定されることから、この仕組みは関連型または連想型(''associated type'')と呼ばれる。
;[[関数オブジェクト]]
:(''function object'')はクラスベースでは、( )[[演算子オーバーロード]]による実装と、[[デリゲート (プログラミング)|デリゲート]]による実装などがある。前者はインスタンスを単に関数名らしく見せるための糖衣構文である。後者のデリゲートは、メソッドシグネチャを型種にした[[関数ポインタ]]型の変数である。デリゲート変数にはインスタンスメソッドへの参照が代入されてそのインスタンス種類による処理の多相を表現できる。プロトタイプベースでは、関数はそのままプロパティ/メソッドを自由に付け替えできる(動的バインディング)オブジェクトになる。それらは同時に関数のローカル変数/関数になる。
;[[コルーチン]]
:オブジェクト指向下の[[イテレータ]]と[[ジェネレータ (プログラミング)|ジェネレータ]]は、コルーチン(''coroutine'')機構に基づいている。通常のサブルーチンがコールする側の復帰アドレスだけをスタックに積むのに対して、コルーチンはコールする側とコールされる側双方の復帰アドレスをスタックに積むというサブルーチン機構である。各要素への作用が記されたオペレータが[[無名関数]]やラムダ式などの形態で[[コンテナ (データ型)|データコンテナ]]に渡されると、各要素をフェッチするデータコンテナと、フェッチされた要素を参照ないし加工するオペレータが交互に[[コールスタック]]を用いて連携動作を繰り返す。イテレータはデータコンテナの各要素にオペレータを適用してその結果値に置き換えていく機能である。ジェネレータは(A)データコンテナを複製してその複製先の各要素にオペレータを適用していくという更新コンテナ生成機能、(B)オペレータがデータコンテナの各要素を選別していき最後に全選別要素を結合したコンテナを生成する機能、(C)オペレータがデータコンテナを走査して各要素の総和値を生成する機能の三種がある。
;[[メッセージ転送|メッセージレシーバー]]
:(''message receiver'')は、メソッド名を文字列で受け取ることができる仕組みであり、インスタンスのデフォルトメソッド(共通窓口メソッド)として備えられるものである。メソッド名の次に引数が渡される。メソッド名文字列はセレクタとも呼ばれる。プログラマはセレクタをレシーバー内で自由に解釈して任意のプロセスに選択分岐できる。通常の<code>instance.method(arg)</code>が、レシーバー機構では<code>instance selector: arg</code>や<code>instance.receiver(method_name, arg)</code>のようになる。受け取ったセレクタによる選択分岐をシステム側が自動化したものがメソッドになった。これの応用形であるメソッドミッシングは、インスタンスに事前定義されていないメソッドが呼び出された時にのみ、取りこぼし用のレシーバーが呼び出されて、文字列化されたメソッド名と引数が渡されるという仕組みである。
;[[イミュータブル|イミュータブル・オブジェクト]]
:(''immutable object'')は、データ不変設定されたクラスのインスタンスを意味する。定数だけを持つインスタンス、不変文字列、不変プリミティブの[[ボックス化|ボックス型]]、収納内容が不変のコレクション(Array、List、Set、Map)などを指す。イミュータブル(不変)はオブジェクトの性質というよりも、それを何のためにどう扱うかというアルゴリズムとデザインパターンの方が要点になる。不変オブジェクトは[[並行計算|並行OOP]]と[[関数型言語|関数型OOP]]で最も重要視される。不変オブジェクトではセッターとミューテイタは禁止され、代わりに元への変更を反映して新たに生成したオブジェクトが返されることになる。コレクションクラスでは要素の追加/削除/変更による結果内容のコレクションが新たに生成されてそれが返り値にされまた引数用途にもなることから、これはファーストクラスコレクションと呼ばれる。なお、不変オブジェクトをコピーした専用の可変オブジェクトを取得したのならば、それへのセッターとミューテイタは許される。これは''copy-on-write''と呼ばれる。


また、RDBMS を代替する[[オブジェクトデータベース]]も存在するが、技術的にも商業的にも RDBMS ほど広く成功は収めていない。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->
;[[委譲|デリゲーション]]
:委譲(''delegation'')。呼び出されたあるクラスのメソッドが自分への引数を他のクラスの同名メソッドにそのまま渡して、その同名メソッドからの返り値をそのまま呼び出し元に渡すという仕組みを指す。委譲先のクラスはhas-a関係で保有されているものになる。委譲先メソッドは必ずしも同名ではなくマッピング名の場合もあり、引数も構成を変えて渡される場合もある。
;フォワーディング
:転送(''forwarding'')。委譲先のクラスのメソッドが処理を行わずに、そのまた他のクラスの同名メソッドに引数をそのまま渡して、その返り値をそのまま呼び出し元に渡している場合、冒頭の委譲は転送になる。転送用メソッドではどのクラスに引数をパスするかという選択が行われるので、デリゲーションの多相を表現できる。


=== OOPと制御構造 ===
;[[派生型|サブタイピング]]
<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->OOPは、ソースコードの[[コードの再利用|コードの再利用性]]や[[ソフトウェア保守|ソフトウェアの保守性]]を高めるよう発展してきたが<ref name="realisticcodereuse">{{Cite web| first = Scott| last= Ambler| title = A Realistic Look at Object-Oriented Reuse| date=1 January 1998| access-date=4 July 2010| publisher = drdobbs.com| url=http://www.drdobbs.com/184415594}}</ref> 、ある時期までは[[制御構造|制御フロー]]の透過的な表現については、あまり省みられることもなく、コンパイラが任意に処理すれば良いと考えられてきた。しかし、OOPでの実現にはある種の困難を伴うものの、並列ハードウェアや[[スレッド (コンピュータ)|マルチスレッドコーディング]]の重要性が増すにつれ透過的な制御フローの開発は重要になってきている<ref name="flaws">{{Cite web| first = Asaf| last= Shelly |title = Flaws of Object Oriented Modeling| date=22 August 2008|access-date=4 July 2010| publisher = Intel Software Network| url=http://software.intel.com/en-us/blogs/2008/08/22/flaws-of-object-oriented-modeling/}}</ref><ref name="multithreadingisaverb">{{Cite web| first = Justin| last = James| title = Multithreading is a verb not a noun| date = 1 October 2007| access-date = 4 July 2010| publisher = techrepublic.com| url = http://blogs.techrepublic.com.com/programming-and-development/?p=518| archive-url = https://web.archive.org/web/20071010105117/http://blogs.techrepublic.com.com/programming-and-development/?p=518| archive-date = 10 October 2007| url-status = dead| df = dmy-all}}</ref><ref name="multicore">{{Cite web| first = Asaf| last= Shelly| title = HOW TO: Multicore Programming (Multiprocessing) Visual C++ Class Design Guidelines, Member Functions| date=22 August 2008| access-date=4 July 2010| publisher = support.microsoft.com| url=http://support.microsoft.com/?scid=kb%3Ben-us%3B558117}}</ref><ref>{{cite web|url=http://existentialtype.wordpress.com/2011/04/17/some-advice-on-teaching-fp/|title=Some thoughts on teaching FP|author=Robert Harper |publisher=Existential Type Blog|access-date=5 December 2011|date=17 April 2011|author-link=Robert Harper (computer scientist)}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->
:(''subtyping'')はクラス(型)のあらゆる派生関係および派生構造の実装形式とその働き方を包括したプログラム概念である。サブタイプ多相(''subtype polymorphism'')とも呼ばれる。継承、オーバーライド、コンポジション、ジェネリクス、共変反変バリアンス、不透明型といったものは全てサブタイピングの一側面である。オブジェクト指向でよく使われるものは、振る舞いサブタイピング(''behavioral subtyping'')であり、継承とメソッドオーバーライドの合わせ技である仮想関数がそれに当たる。


=== 責任駆動設計 対 データ駆動設計 ===
;[[Is-a|Is-a関係]]
<!-- ここから [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->[[:en:Responsibility-driven design|責任駆動設計]]では、クラスは、共有する情報とそれを扱う責務という観点から定義されるべきであるとし、クラス定義 (とその利用者)の契約として設計する。Wirfs-BrockとWilkersonは、責任駆動設計と対比して、[[:en:Data-driven programming|データ駆動設計]]は、クラスが保持すべきデータ構造のみを中心に定義されるとし、責任駆動型の設計が望ましいとしている<ref name="Wirfs-Brock1989">{{cite journal|last1=Wirfs-Brock|first1=Rebecca|last2=Wilkerson|first2=Brian|title=Object-Oriented Design: A Responsibility-Driven Approach|journal=ACM SIGPLAN Notices|date=1989|volume=24|issue=10|page=74|doi=10.1145/74878.74885}}</ref>。<!-- ここまで [[en:Object-oriented programming]] oldid=1057169575 の翻訳 -->
:(''Is-a'')は[[上位概念、下位概念、同位概念および同一概念|上位概念と下位概念]]のコンセプトを扱っており、下位概念is-a上位概念となる。オブジェクト指向ではクラスの継承関係および実装継承関係を意味する用語になっている。これには汎化・特化・実現・実装の四種がある。
:* 汎化(''generalization'')は、サブクラスからスーパークラスへの連結を指す。
:* 特化(''specialization'')は、スーパークラスからサブクラスへの連結を指す。
:* 実現(''realization'')は、クラスからインターフェースへの連結を指す。
:* 実装(''implementation'')は、インターフェースからクラスへの連結を指す。
;[[Has-a|Has-a関係]]
:(''Has-a'')は[[部分集合|上位集合と部分集合]]のコンセプトを扱っており、上位集合has-a部分集合となる。オブジェクト指向ではクラスの構成関係を意味する用語になっている。これには合成・集約・収容・依存の四種がある。なお、依存(''dependency'')はhas-a関係における依存とそれ以外のクラス間関係における依存の意味が異なる二つが存在する。
:* 合成(''composition'')は強いhas-a関係であり、AクラスがBクラスをデータにし、Aクラスのコンストラクタと同時にBインスタンスが生成され、Aクラスのデストラクタと同時にBインスタンスが破棄される場合、AはBの合成となる。Bが自身のサブクラスで交換される場合は分離とともに破棄される。
:* 集約(''aggregation'')は弱いhas-a関係であり、AクラスがBクラスをデータにし、Aクラスのコンストラクタとは関係なくBインスタンスが生成され、AクラスのデストラクタでBインスタンスが破棄されず、また分離時も破棄されない場合、AはBの集約となる。Aクラスがコレクション(配列、List、Set、Map)の仕組みでBインスタンスを持つ場合も、AはBの集約となる。
:* 収容(''containment'')は弱いhas-a関係であり、集約と同じであるが、Aクラスがコレクション(配列、List、Set、Map)の仕組みでBインスタンスを持つ場合のみを指している。コレクション関係を強調する場合、AはBを収容しているとなる。
:* 依存(''dependency'')は強いhas-a関係であり、Aクラスのいずれかのメソッドが、Bクラスを引数の型または返り値の型にしている場合、AはBに依存しているとなる。なお、AクラスがBクラスの型のデータを[[has-a]]している場合のAからBへの依存は、合成/集約の方で省略されている。


=== <!-- 以下、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->SOLID、GRASPのガイドライン ===
;[[SOLID|SOLID原則]]
:(''SOLID Principles'')は、いわゆる抽象化に焦点を当てたクラスの設計原則である。(S)単一責任原則・(O)解放閉鎖原則・(L)リスコフの置換原則・(I)インターフェース分離原則・(D)依存性逆転原則といった五つから成り立っている。1988年に[[バートランド・メイヤー]]が提唱した(O)と、1994年に[[バーバラ・リスコフ]]が提示した(L)に、ソフトウェア技術者ロバート・マーティンが(S)(I)(D)を加えて2000年に発表されている。
:* (S){{仮リンク|単一責任原則|en|Single-responsibility principle}}は、クラスをただ一つの機能を表現するようにデザインすることを推奨している。
:* (O)[[開放/閉鎖原則|解放閉鎖原則]]は、クラスを抽象クラスと実装クラスに分けてデザインすることを推奨している。抽象クラスの定義内容は変更に閉じられており、実装クラスの処理内容は拡張に開かれていることが由来である。
:* (L)[[リスコフの置換原則]]は、実装クラスはその抽象クラスに対して振る舞い的に等価計算が可能であることを推奨している。抽象側の公開保有メソッドを実装側も全て保有していれば等価となる。ここでの置換(''substitution'')とは抽象クラスの型の変数に実装クラスの型のインスタンスを代入できることを意味している。
:* (I){{仮リンク|インターフェース分離原則|en|Interface segregation principle|label=}}は、一つのクラスから実現される抽象クラスを一つに限定せず、互いに処理内容に影響し合うメソッド群ごとに分離して複数実現することを推奨している。
:* (D)[[依存性逆転の原則|依存性逆転原則]]は、AクラスがBクラスの機能を使用したい場合は、まずBからその抽象クラスをAに向けて実現し、Aはその抽象クラスを通してBの機能を使用することを推奨している。AはBの機能を使用するという意味でその抽象クラスに依存し、Bは自身の機能を提供するという意味でその抽象クラスに依存することになる。ここでの逆転(''inversion'')とは実装から抽象への方向性を意味している。


[[SOLID]]のガイドラインは、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ<ref>https://wiki.c2.com/?MichaelFeathers</ref>が考案し提唱したものである
; [[デザインパターン (ソフトウェア)|GOFデザインパターン]]
* '''S''' : [[:en:Single responsibility principle|単一責任の原則(英語版)]]
: (''Gang of Four Design Patterns'')はソフトウェア開発において直面しやすい共通的かつ代表的なデザイン問題をピックアップし、それぞれの解決に最適なクラスパターン図を提示したものである。1994年から四人の計算機科学者ないしソフトウェア技術者たち([[Gang of Four]])によって発表され、OOPのデザインパターンの代表格と見なされた。教科書の内容としても取り上げやすい形式化されたトピックであったためにオブジェクト指向の学習面では非常に重視された。5個の生成パターン、7個の構造パターン、11個の振る舞いパターンに分類されている。
* '''O''' : [[開放/閉鎖原則]]
: 生成に関するパターン<gallery heights="40">
* '''L''' : [[リスコフの置換原則]]
ファイル:Abstract Factory UML class diagram.svg|[[Abstract Factory パターン|Abstract factory]]
* '''I''' : [[:en:Interface segregation principle|インターフェイス分離の原則(英語版)]]
ファイル:Builder UML class diagram.svg|[[Builder パターン|Builder]]
* '''D''' : [[依存性逆転の原則]]
ファイル:Factory Method UML class diagram.svg|[[Factory Method パターン|Factory Method]]

ファイル:Prototype UML.svg|[[Prototype パターン|Prototype]]
[[GRASP]](General Responsibility Assignment Software Patterns)は、[[:en:Craig Larman|クレーグ・ラーマン]]が提唱したもう一つガイドラインである。
ファイル:Singleton UML class diagram.svg|[[Singleton パターン|Singleton]]
<!-- 以上、[[en:Object-oriented programming]] oldid=1047374345 の翻訳 -->
</gallery>

: 構造に関するパターン<gallery heights="40">
== 形式意味論 ==
ファイル:Adapter pattern UML diagram.PNG|[[Adapter パターン|Adapter]]
{{see also|プログラム意味論}}
ファイル:Bridge UML class diagram.svg|[[Bridge パターン|Bridge]]
ファイル:Composite UML class diagram (fixed).svg|[[Composite パターン|Composite]]
ファイル:Decorator UML class diagram.svg|[[Decorator パターン|Decorator]]
ファイル:Facade UML class diagram.svg|[[Facade パターン|Facade]]
ファイル:Flyweight UML class diagram.svg|[[Flyweight パターン|Flyweight]]
ファイル:UML DP Proxy.png|[[Proxy パターン|Proxy]]
</gallery>
: 振る舞いに関するパターン<gallery heights="40" perrow="11">
ファイル:Chain of responsibility UML diagram.png|[[Chain of Responsibility パターン|Chain of Responsibility]]
ファイル:Command Design Pattern Class Diagram.png|[[Command パターン|Command]]
ファイル:InterpreterUMLDiagramm.png|[[Interpreter パターン|Interpreter]]
ファイル:Iterator UML class diagram.svg|[[Iterator パターン|Iterator]]
ファイル:Mediator design pattern.png|[[Mediator パターン|Mediator]]
ファイル:Memento design pattern.png|[[Memento パターン|Memento]]
ファイル:Observer UML smal.png|[[Observer パターン|Observer]]
ファイル:State Design Pattern UML Class Diagram.svg|[[State パターン|State]]
ファイル:Strategy Pattern in UML.png|[[Strategy パターン|Strategy]]
ファイル:Template Method UML class diagram.svg|[[Template Method パターン|Template Method]]
ファイル:Visitor UML class diagram.svg|[[Visitor パターン|Visitor]]
</gallery>


== 脚注 ==
== 脚注 ==
{{脚注ヘルプ}}
{{脚注ヘルプ}}
=== 注釈 ===
{{Notelist2}}
=== 出典 ===
{{Reflist}}
{{Reflist}}

== 出典 ==
* {{Cite journal
|last=Kindler
|first=E.
|last2=Krivy
|first2=I.
|year=2011
|title=Object-Oriented Simulation of systems with sophisticated control
|pages=313–343
|publisher=International Journal of General Systems
|ref=harv
}}
* {{Cite book
|last=Lewis
|first=John
|last2=Loftus
|first2=William
|title=Java Software Solutions Foundations of Programming Design
|edition=6th
|year=2008
|publisher=Pearson Education Inc.
|isbn=978-0-321-53205-3
|ref=harv
}}
* {{cite web2
|last=Kay
|first=Alan
|last2=Ram
|first2=Stefan
|title=Dr. Alan Kay on the Meaning of “Object-Oriented Programming”
|url=https://www.purl.org/stefan_ram/pub/doc_kay_oop_en
|website=www.purl.org
|access-date=2022-08-15
|date=2003-07-23
|ref={{sfnref|Meaning|2003}}
}}
* {{Cite journal
|last=McCarthy
|first=J.
|last2=Brayton
|first2=R.
|last3=Edwards
|first3=D.
|last4=Fox
|first4=P.
|last5=Hodes
|first5=L.
|last6=Luckham
|first6=D.
|last7=Maling
|first7=K.
|last8=Park
|first8=D.
|last9=Russell
|first9=S.
|date=March 1960
|title=LISP I Programmers Manual
|url=http://history.siam.org/sup/Fox_1960_LISP.pdf
|page=88f
|publisher=Artificial Intelligence Group, [[:en:M.I.T. Computation Center]] and Research Laboratory
|author2-link=:en:Robert Brayton (computer scientist)
|author3-link=:en:Daniel Edwards (programmer)
|author4-link=:en:Phyllis Fox
|author5-link=:en:Louis Hodes
|author6-link=:en:David Luckham
|author7-link=:en:Klim Maling (programmer)
|author8-link=:en:David Park (computer scientist)
|author9-link=:en:Steve Russell (computer scientist)
|place=[[ボストン]], [[マサチューセッツ]]
|quote=In the local M.I.T. patois, association lists [of atomic symbols] are also referred to as "property lists", and atomic symbols are sometimes called "objects".
|url-status=dead
|archive-date=17 July 2010
|archiveurl=https://web.archive.org/web/20100717111134/http://history.siam.org/sup/Fox_1960_LISP.pdf
|ref={{sfnref|LISP 1 Programmers Manual|1960}}
}}
* {{Cite book
|last=McCarthy |first=John
|author-link=:en:John McCarthy (computer scientist)
|title=LISP 1.5 Programmer's Manual
|url=https://archive.org/details/lisp15programmer00john/page/105
|year=1962
|publisher=[[:en:MIT Press]]
|isbn=978-0-262-13011-0
|page=[https://archive.org/details/lisp15programmer00john/page/105 105]
|quote=Object&nbsp;— a synonym for atomic symbol
|last2=Abrahams
|first2=Paul W.
|last3=Edwards
|first3=Daniel J.
|author3-link=:en:Daniel Edwards (programmer)
|last4=Hart
|first4=swapnil d.
|last5=Levin
|first5=Michael I.
|df=dmy-all
|ref={{sfnref|LISP 1.5 Programmers Manual|1962}}
}}
* {{Cite web
|url=http://handle.dtic.mil/100.2/AD404549
|title=Sketchpad: A Man-Machine Graphical Communication System
|last=Sutherland
|first=I. E.
|date=1963-01-30
|publisher=Technical Report No. 296, Lincoln Laboratory, Massachusetts Institute of Technology via Defense Technical Information Center (stinet.dtic.mil)
|access-date=17 July 2019
|ref={{sfnref|Sutherland|1963}}
}}
* {{cite book
|last1=Ali
|first1=Junade
|title=Mastering PHP Design Patterns
|date=2016-09-28
|publisher=Packt Publishing Limited
|location=Birmingham, England, UK
|isbn=978-1-78588-713-0
|edition=1
|language=en
|ref=harv
}}
* {{cite journal
|last1=Nygaard
|first1=Kristen
|last2=Dahl
|first2=Ole-Johan
|title=Development of the SIMULA languages
|journal=ACM SIGPLAN Notices
|pages=245–272
|volume=13
|issue=8
|publisher=Association for Computing Machinery
|date=1978-08-01
|doi=10.1145/960118.808391
|ref=harv
}}
* {{Cite journal
|last = Dahl
|first = Ole Johan
|year = 2004
|chapter-url = http://www.mn.uio.no/ifi/english/about/ole-johan-dahl/bibliography/the-birth-of-object-orientation-the-simula-languages.pdf
|doi = 10.1007/978-3-540-39993-3_3
|chapter = The Birth of Object Orientation: The Simula Languages
|title = From Object-Orientation to Formal Methods
|volume = 2635
|pages = 15–25
|series = Lecture Notes in Computer Science
|isbn = 978-3-540-21366-6
|citeseerx = 10.1.1.133.6730
|access-date = 22 October 2021
|ref=harv
}}
* {{Cite journal
|first=Alan
|last=Kay
|title=The Early History of Smalltalk
|journal=ACM SIGPLAN Notices
|volume=28
|issue=3
|date=1993-03-01
|pages=69–95
|doi=10.1145/155360.155364
|publisher=Association for Computing Machinery
|ref=harv
}}
* {{Cite journal
|last = Holmevik
|first = Jan Rune
|title = Compiling Simula: A historical study of technological genesis
|journal = IEEE Annals of the History of Computing
|volume = 16
|issue = 4
|pages = 25–37
|year = 1994
|doi = 10.1109/85.329756
|s2cid = 18148999
|ref=harv
}}
* {{Cite book
|title=Touch of Class: Learning to Program Well with Objects and Contracts
|first=Bertrand
|last=Meyer
|publisher=Springer Science & Business Media
|year=2009
|isbn=978-3-540-92144-8
|pages=329
|bibcode=2009tclp.book.....M
|ref=harv
}}


== 関連項目 ==
== 関連項目 ==
<!-- ここから [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->
<!-- * [[Comparison of programming languages (object-oriented programming)]] -->
<!-- * [[Comparison of programming paradigms]] -->
<!-- * [[Component-based software engineering]] -->
* [[契約プログラミング]]
<!-- * [[Object association]] -->
* [[オブジェクトデータベース]]
<!-- * [[Object model reference]] -->
<!-- * [[Object modeling language]] -->
* [[オブジェクト指向分析設計]]
<!-- * [[Object-relational impedance mismatch]] (and [[The Third Manifesto]]) -->
* [[オブジェクト関係マッピング]]

=== システム ===
* [[:en:CADES|CADES]]
* [[Common Object Request Broker Architecture]] (CORBA)
* [[Distributed Component Object Model]]
* [[:en:Distributed Data Management Architecture|Distributed Data Management Architecture]]
* [[:en:Jeroo|Jeroo]]

=== モデリング言語 ===
* [[:en:IDEF4|IDEF4]]
* [[インタフェース記述言語]]
* [[:en:Lepus3|Lepus3]]
* [[統一モデリング言語|UML]]
<!-- ここまで [[en:Object-oriented programming]] oldid=1055370410 の翻訳 -->


{{Normdaten}}
{{Normdaten}}

2024年8月3日 (土) 12:42時点における最新版

オブジェクト指向プログラミング(オブジェクトしこうプログラミング、: object-oriented programming, OOP)とは、「オブジェクト」という概念に基づいたプログラミングパラダイムの一つである。

OOPでは、相互に作用するオブジェクトを組み合わせてプログラムを設計する[1][2]

OOPの方法として、クラスベースOOPとプロトタイプベースOOPがある。 クラスベースOOPでは、オブジェクトが属する集合としてクラスを定義し、クラス定義からそのインスタンスとしてオブジェクトを生成する。 プロトタイプベースOOPでは既存のオブジェクト(プロトタイプ)を複製し、プロトタイプの複製に変更を加えることで様々な対象を表すオブジェクトを生成する。

広く使われているプログラミング言語の多く、例えばC++JavaPythonなどは、マルチパラダイムであるが、程度の差はあれ、オブジェクト指向プログラミングをサポートしており、大抵は命令型手続き型プログラミングとの組み合わせで用いられる。

歴史

[編集]
UMLによるクラスの表記法。この Button クラスは、データを表す変数(図中 xsize など)と関数(図中 draw() など)を持つ。一般的なクラスは継承によりサブクラスを持つことができる。また、オブジェクトはクラスのインスタンスである。

アラン・ケイによれば “object-oriented”(オブジェクト指向)という言葉は、1967年ごろケイ自身が考案したものであるという[3]。しかし、現在のオブジェクト指向プログラミングという文脈における「オブジェクト」や「指向」を表す用語が初めて登場したのは、1950年代後半から1960年代前半にかけてのマサチューセッツ工科大学(MIT)においてである。 1960年代初頭の人工知能グループ界隈では、「オブジェクト」はプロパティ(属性)を持つ個体識別可能なアイテム(LISPの atom)を意味していた[4][5]。 後にケイは、1966年にLISPの内部構造を詳細に理解したことが彼の考え方に強い影響を与えたと述べている[3]

私は、オブジェクトとは、生物の細胞やネットワーク上の個々のコンピュータのようもの、そしてそれらのコミュニケーションは専らメッセージによって行なわれるもの、と考えていました (つまり、メッセージングは最初から存在していたのですが、プログラミング言語でメッセージングを実用的かつ効率的に行う方法を見つけるまでには時間がかかりました)。
アラン・ケイ, (Meaning 2003)

MITにおける初期の例としては、この他にも、1960年から1961年にかけてアイバン・サザランドが作成したSketchpadが挙げられる。サザランドは、1963年の技術レポートの用語集 (Sketchpadに関する自身の博士論文をもとにしたもの)で、グラフィカルなインタラクションに特化しているとはいえ「オブジェクト」と「インスタンス」の概念を定義している (クラスの概念は"master"または"definition"として把握されている)。[6] また、MIT版のALGOLであるAED-0では、データ構造 (この言語の方言では"plexes"と呼称)と手続きを直接結びつけ、後に「メッセージ」、「メソッド」、「メンバ関数」と呼ばれるようなものの萌芽がみられる。[7]

1962年、クリステン・ニゴールノルウェー計算センター英語版でシミュレーション言語のプロジェクトを開始した。これは彼が以前に用いたモンテカルロ法と実世界のシステムを概念化する仕事に基づくものであった。オーレ=ヨハン・ダールが正式にプロジェクトに参加し、UNIVAC I (UNIVAC 1107) 上で動作するSimulaプログラミング言語が設計された。Simulaは、クラスオブジェクト、継承、ダイナミックバインディングなど、今日のオブジェクト指向プログラミングには不可欠である重要な概念を導入した。[8] Simulaはまた、プログラミングにおけるデータ保全英語版を考慮して設計されたものでもあった。プログラミングのデータ保全のために参照カウントによる検出プロセスが実装されたのに加え、最終手段としてガベージコレクタ主記憶装置(メモリ)内の使用されていないオブジェクトを削除するようになっていた。しかし、データオブジェクトの概念は1965年には既に確立されていたものの、プライベートやパブリックといった変数スコープのレベルによるデータのカプセル化については、アクセスする手続きもまた隠蔽できなければならなかったため、Simulaでは実装されなかった。[9]

初期の段階では、Simulaはプログラミング言語ALGOL 60のための手続きパッケージとされていた。しかし、ALGOLによる制約に不満を感じた研究者たちは、UNIVAC ALGOL 60コンパイラを使用した本格的なプログラミング言語としてSimulaを開発することにした。ダールとニゴールは1965年から1966年にかけてSimulaの普及に尽力し、スウェーデン、ドイツ、ソビエト連邦などでSimulaの使用が増加した。1968年には、バロース B5000上で広く利用されるようになり、後にはURAL-16コンピュータ上にも実装された。1966年、ダールとニゴールはSimulaのコンパイラを書いた。彼らは、SIMSCRIPT英語版 (自由形式の英語的な汎用シミュレーション言語)を実装に用いて、アントニー・ホーアのレコード・クラス概念を取り入れることに熱心に取り組んだが、彼らは、一般化されたプロセスの概念として、レコード・クラスの属性を保持する層と、接頭辞 (prefix) の系列を保持する層の二層構造とする方式に辿り着いた。 接頭辞の系列を通じて、プロセスは先行する定義を参照し、それらの属性を追加することができる。このようにしてSimulaは、クラスとサブクラスの階層を導入し、これらのクラスからオブジェクトを生成することを可能にする方法を導入することとなった。[7]

1972年にはIBM System/360およびIBM System/370IBMメインフレーム用にSimula 67コンパイラが完成[8]。同年、フランスのCII 10070およびCII Iris 80メインフレーム用のSimula 67コンパイラが無償で提供された。1974年には、Simulaユーザー会は23カ国のメンバーを有するまでになっていた。1975年初頭、DECsystem-10メインフレームファミリー用のSimula 67コンパイラが無償でリリースされ、同年8月までにDECsystem-10のSimula 67コンパイラは28サイトにインストールされた (そのうちの22サイトは北米)。オブジェクト指向のプログラミング言語としてSimulaは、貨物港における船舶と積載貨物の動きを調査・改善するための研究のような、物理モデリングの研究に携わる研究者に主に利用されていた[8]

1970年代、Xerox パロアルト研究所(PARC)において、アラン・ケイダン・インガルスアデル・ゴールドバーグらによって、プログラミング言語Smalltalkの最初のバージョンが開発された。Smaltalk-72はプログラミング環境を含み、動的型付けであり、当初はコンパイルしてからの実行ではなくインタプリタ実行であった。Smalltalkは、言語レベルでのオブジェクト指向の適用と、グラフィカルな開発環境で注目されたが、Smalltalkが様々なバージョンを経て成長するにつれ、この言語への関心も高まっていった[10]。 SmalltalkはSimula 67で導入されたアイデアの影響を受けてはいるものの、クラスを動的に生成・変更できるなど、完全に動的なシステムとして設計された[11]

1970年代、SmalltalkはLispコミュニティに影響を与え、Lispコミュニティは、Lispマシンを通じて開発者に紹介されたオブジェクトベースの技術を取り入れた。Lispの様々な拡張機能(LOOPS やFlavors英語版などが導入した多重継承Mixin)の試みは、最終的に関数型プログラミングとオブジェクト指向プログラミングを統合し、メタオブジェクト・プロトコル英語版による拡張を可能にしたCommon Lispのオブジェクト指向システム (CLOS) へとつながった。 1980年代には、メモリ上のオブジェクトをハードウェアでサポートするプロセッサ・アーキテクチャを設計する試みがいくつか行われたが、Intel iAPX 432Linn SmartRekursiv英語版など、いずれも商業的に成功しなかった。

1981年、ゴールドバーグはByte Magazine 8月号のSmalltalk特集号で、Smalltalkとオブジェクト指向プログラミングをより多くの人々に紹介した。 1986年、ACMが主催する第一回OOPSLAが開催され、予想に反して1,000人が参加した。1980年代半ばには、ITTでSmalltalkを使っていたブラッド・コックスによってObjective-Cが開発され、博士論文でSimulaを扱っていたビャーネ・ストロヴストルップよってオブジェクト指向のC++が作られた[10]。 1985年には、バートランド・メイヤーEiffelの最初の設計を行った。ソフトウェアの品質に焦点を当てたEiffelは、純粋なオブジェクト指向プログラミング言語であり、ソフトウェアのライフサイクル全体をサポートする記法をもつ。メイヤーは、ソフトウェア工学とコンピュータサイエンスの少数の重要なアイデアに基づいたEiffelでのソフトウェア開発手法をオブジェクト指向入門英語版で解説している。Eiffelでは、メイヤーが開発した信頼性担保の機構である契約プログラミングが、開発手法と言語の双方に不可欠な要素となっている。

TIOBE プログラミング言語の人気ランキングの2002年から2018年のグラフ。2000年代のオブジェクト指向言語Java (青)と手続き型プログラミング言語C (黒)の首位争いの様子

1990年代前半から半ばにかけて、オブジェクト指向プログラミングは、その技術をサポートするプログラミング言語が広く普及したことにより、プログラミングパラダイムとして主要なものとなった。その中には、Visual FoxPro 3.0[注 1][12][13]C++[14]Delphi[15]などがある。 その勢力は、オブジェクト指向プログラミング技術に支えられたグラフィカルユーザインタフェースの人気向上と共に高まった。動的なGUIライブラリとOOP言語が密接に連携している例としては、Smalltalkを規範にしたCのオブジェクト指向の動的メッセージング拡張であるObjective-Cで書かれたmacOSCocoaフレームワークなどが挙げられる。また、OOPツールキットの存在は、イベント駆動型プログラミングの人気を高めることにも繋がった(ただし、この概念はOOPに限定されるものではない)。 チューリッヒ工科大学では、ニクラウス・ヴィルトらが、データ抽象化モジュール化プログラミング英語版などの研究を行っていた (ただし、これらは1960年代以前にも一般的に使われてはいた)。 1978年に発表されたModula-2にはこの2つが盛り込まれており、その後に発表されたOberonでは、オブジェクト指向やクラスなどに対する独自のアプローチが盛り込まれている[16]

オブジェクト指向の機能は、AdaBASICFortranPascalCOBOLなど、既存の多くの言語に追加されていったが、しかし、設計当初にこれらの機能を想定していなかった言語に追加した場合、コードの互換性や保守性には問題が生じることが多かった。

最近では、主としてオブジェクト指向でありながら、手続き型プログラミングの方法論にも対応した言語が数多く登場している。そのような言語としては、PythonRubyがある。最近の商業的なオブジェクト指向言語で最も重要なものには、サン・マイクロシステムズ社が開発したJavaや、Microsoftの.NETプラットフォーム用に設計されたC#Visual Basic .NET (VB.NET) が挙げられる。 これら二つのフレームワークは、実装を抽象化することによるOOP使用の利点をそれぞれの方法で示している。VB.NETとC#間では言語間継承をサポートしており、一方の言語で定義されたクラスが他方の言語で定義されたクラスをサブクラス化することができる[17]

OOPLの特徴

[編集]

オブジェクト指向プログラミング言語 (OOPL) では、オブジェクトを使用するが、言語仕様でOOP対応を謳っていても、関連する技術や構造のすべてが言語機能により直接サポートされているわけではない。以下に挙げる特徴は、特に言及されている例外を除いて、クラス指向やオブジェクト指向の傾向が強いとされる言語 (あるいはOOPをサポートするマルチパラダイムプログラミング言語)に共通すると考えられるものである。

非OOPLとの共通点

[編集]
変数
整数型や英数字の文字のような形式化された少数の組み込みデータ型の情報、または、文字列リストハッシュテーブルなどのデータ構造に、組み込み型もしくは、ポインタが格納されたものを結果として格納することができる。
手続き(関数、メソッド、サブルーチンとも呼ばれる)
入力を受け取り、出力を生成し、データを操作する。近年の言語には、ループ条件構文のような構造化プログラミングの構成要素が含まれる。

モジュラープログラミングサポートでは、手続きをファイルやモジュールにまとめて整理する機能がある。モジュールは名前空間を持つため、あるモジュールの識別子が、他のモジュールの同名の手続きや変数と衝突することを避けることができる。

クラスとオブジェクト

[編集]

オブジェクト指向プログラミング(OOP)をサポートする言語は、コードの再利用と拡張性のために、典型的には、クラスまたはプロトタイプの形で継承を使用する。クラスを使用するものは、主に二つの概念をサポートする。

クラス
与えられた型やクラスのオブジェクトのデータ形式やそれらを利用可能な手続きの定義であり、また、データや手続き (クラスメソッドとも呼ばれる)そのものを含む場合もある。つまり、クラスは、メンバーとなるデータや手続きを含むものである。
オブジェクト
クラスのインスタンス

オブジェクトは、システムが扱おうとする(多くは現実世界の)対象を表現したものである。例えば、描画アプリケーションにおける「円」・「四角」・「メニュー」などのオブジェクトや、オンラインショッピングシステムにおける「ショッピングカート」・「顧客」・「商品」などのオブジェクトがある[18]。 オブジェクトは、ファイルのオープンを表すオブジェクトや、米国慣用単位からメートル法に変換するサービスを提供するオブジェクトのように、より抽象的なエンティティを表すこともある。

オブジェクト指向プログラミングとは、単なるクラスやオブジェクトではなく、データフィールドやメソッドを含んだオブジェクト (データ構造)を中心としたプログラミングパラダイム全般のことです。クラスを使って、関係のないメソッドをまとめて整理する——これがオブジェクト指向の本質ではないことを理解しましょう。
Junade Ali, Mastering PHP Design Patterns(Ali 2016, p. 11)

各々のオブジェクトは、特定のクラスのインスタンスと呼ばれる (例えば、nameフィールドに "Mary"が設定されているオブジェクトは、クラスEmployeeのインスタンスとなる)。OOPの手続きはメソッドと呼ばれ、変数は、フィールド、メンバー、属性、プロパティとも呼ばれる。関連して、以下のような用語がある

クラス変数
クラス自体に属する。変数をクラス全体に唯一のものとして所有する。
インスタンス変数または属性
各々のオブジェクトに属する。データはオブジェクトごとに所有する。
メンバ変数
特定のクラスで定義されるクラス変数とインスタンス変数の両方を指す。
クラスメソッド
クラス自体に属する。クラス変数へのアクセスのみ有し、手続き呼び出しからの入力のみ受け付ける。
インスタンスメソッド
各々のオブジェクトに対して、呼び出された特定のオブジェクトのインスタンス変数、入力、およびクラス変数にアクセスできる。

オブジェクトは、複雑な内部構造を持った変数のようにアクセスされるが、多くの言語で実質的にはポインタでありインスタンス (ヒープやスタック内のメモリ上オブジェクト)への参照として機能する。オブジェクトは、内部コードと外部コードを分離を可能とする抽象化の層を提供する。外部のコードは、特定の入力引数の組み合わせで特定のインスタンスメソッドを呼び出したり、インスタンス変数を読み込んだり、インスタンス変数に書き込んだりすることで、オブジェクトを使用することができる。オブジェクトは、コンストラクタと呼ばれるクラス内の特定メソッドを呼び出すことで生成される。プログラムは実行中に、それぞれ独立して操作することが可能な同じクラスのインスタンスを多数作成することができる。これは、同じ手続きを異なるデータセットで簡便に利用する方法となる。

クラスを使用するOOPをクラスベース・プログラミングと呼ぶことがあるが、プロトタイプベース・プログラミングではクラスを使用しないのが一般的である。そのため、オブジェクトインスタンスという概念の定義は、それぞれで大きく異なるが類似した用語が用いられている。

言語によっては、トレイトmixinのような概念を用いてクラスやオブジェクトを構成することが可能である。

クラスベース対プロトタイプベース

[編集]

クラスベースの言語では、予めクラスが定義され、そのクラスに基づいてオブジェクトがインスタンス化される。例えば、appleorangeという2つのオブジェクトが、Fruitというクラスからインスタンス化された場合、それらは本質的には果物であり、同じように取り扱えることの保証がされる。

プロトタイプベースの言語では、オブジェクトが主要な実体である。クラスは存在しない。オブジェクトのプロトタイプとは、あるオブジェクトからリンクされている別のオブジェクトに過ぎない。すべてのオブジェクトは一つのプロトタイプリンクを持つ (一つのみ)。新しいオブジェクトは、プロトタイプとして選ばれた既存のオブジェクトに基づいて作成することができる。fruitオブジェクトが存在し、appleorangeの両方がfruitをプロトタイプとしている場合、2つの異なるオブジェクトappleorangeを果物と考えることができる。fruit「クラス」という概念は明示的には存在しないが、同じプロトタイプを共有するオブジェクトの同値クラスとしては存在する。プロトタイプの属性やメソッドは、このプロトタイプで定義された同値クラスのすべてのオブジェクトから委譲先とされる。オブジェクト固有の属性やメソッドは、同値クラスの他のオブジェクトに共有されない場合がある。例えば、属性sugar_contentappleには予期せず存在しない場合がある。プロトタイプで実装できるのは単一継承のみである。

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

[編集]

メソッドの呼び出しに応じて実行する手続きのコードを選択するのは、外在するコードではなく、オブジェクトの責任である。典型的には、オブジェクトに関連付けられたテーブルから実行時にメソッドを検索するが、この機能は動的ディスパッチとして知られており、抽象データ型 (またはモジュール)において、すべてのインスタンスの操作が静的に実装されているのとは対照的である。呼び出しの変化が、呼び出されたオブジェクトの単一の型にのみには依らない場合 (つまり複数のオブジェクトがメソッド選択に関与する場合)、多重ディスパッチと呼ばれる。

メソッド呼び出しは、メッセージパッシングとも呼ばれる。これは、メソッド呼び出しを、ディスパッチのためにオブジェクトに渡されるメッセージ (メソッドの名前とその入力引数)として概念化したものである。

カプセル化

[編集]

カプセル化とは、オブジェクト指向プログラミングにおいて、データとそのデータを操作する関数を結び付け、両者を外部からの干渉や誤用から守ることである。データのカプセル化は、OOPの重要な概念である情報隠蔽英語版にも通じる。

クラスがメソッドを通じてのみオブジェクトの内部データへのアクセスを許可し、それ以外の呼び出しコードにアクセスを許可しない場合、これはカプセル化として知られる強力な抽象化、または情報隠蔽の形態である。いくつかの言語 (Javaなど)では、クラスがアクセス制限を明示的に行うことができる。例えば、内部データであることをprivateというキーワードで指定し、クラス外のコードが使用することを意図したメソッドをpublicというキーワードで指定することができる。また、メソッドはpublic、private、またはprotected (同クラスとそのサブクラスからのアクセスは許可するが、異なるクラスのオブジェクトからのアクセスは許可しない)のように中間のアクセスレベルとすることもできる。また他の言語 (Pythonなど)では、アクセス制限は、命名法などの慣例によってのみ強制される (例えば、privateのメソッドはアンダースコアで始まる名前を持つ、など)。カプセル化することで、外部のコードがオブジェクトの内部動作に関与してしまうことを防ぐことができ、リファクタリングを容易にする。例えば、クラスの設計者は、外部のコードは変更することなく、そのクラスのオブジェクト内部のデータ表現を変更することができる (公開されているメソッドの呼び出しが同じように動作する限りにおいて)。また、特定のデータに関連するすべてのコードを同じクラスに配置することで、他のプログラマが理解しやすいように整理することもできる。カプセル化は、疎結合を促進する技術である。

コンポジション、継承、委譲

[編集]

オブジェクトは、そのインスタンス変数に他のオブジェクトを含めることができ、これをオブジェクトコンポジションと呼ぶ。例えば、"従業員"クラスのオブジェクトは、"名前" や "役職"といった自身のインスタンス変数に加えて、"住所"クラスのオブジェクトを (直接またはポインタを介して)含むことができる。 オブジェクトコンポジションは、"has-a" の関係を表現するために使用できる。例えば、すべての従業員は住所を持っているので、すべての"従業員"オブジェクトは、"住所"オブジェクトを格納する場所 (オブジェクトに直接埋め込まれていることも、ポインターで指定された別の場所に格納されることもある)にアクセスできる。

クラスをサポートする言語は、大抵は継承をサポートしている。継承とは、クラスを「○○は△△である」という関係("is-a-type-of")の階層に配置することであるが、例えば、Employee クラスは Person クラスを継承する場合、親クラスで利用できるデータやメソッドは、子クラスでも同じ名前で利用可能である。また、Person クラスは、first_namelast_name という変数を make_full_name() というメソッドで定義した場合、これらの定義はEmployeeクラスでも利用可能である。加えて、Employeeクラスには変数 positionsalary を追加することもできる。この手法では、同じ手続きやデータ定義を簡単に再利用できるだけでなく、現実世界の関係を直感的に反映できる可能性を広げる。開発者は、データベースのテーブルやプログラミングのサブルーチンを扱うのではなく、開発アプリケーションのユーザーがより精通しているドメインのオブジェクトを扱うことができる[19]

サブクラスはスーパークラスで定義されたメソッドをオーバーライドできる。言語よっては多重継承が可能だが、多重継承ではオーバーライドの解決は複雑になる可能性がある。また、言語によってはmixinを特別にサポートしているものもあるが、多重継承をサポートする言語では、mixinは単に is-a-type-of の関係を表すことのないクラスの一つである。mixinは典型的には、同一のメソッドを複数のクラスに追加するために使われる。例えば、共通の親クラスを持たないFileReaderクラスとWebPageScraperクラスに、unicode_to_ascii()というメソッドを持つUnicodeConversionMixinクラスを含ませる(mixinする)ことにより共通のメソッドを提供することができる。

抽象クラスは、オブジェクトへインスタンス化することはできない。インスタンス化できる他の具象クラスが継承するためにのみ存在する。Javaでは、finalキーワードを用いて、クラスがサブクラス化されるのを防止できる。

Composition over inheritanceの方針は、継承の代わりに合成を使って has-a 関係を実装することを提唱している。例えば、EmployeeクラスはPersonクラスを継承する代わりに、各Employeeオブジェクトの内部にPersonオブジェクトを含めることで、仮にPersonクラスが公開された属性やメソッドを多数持っていても、外部のコードからは隠せるようにする。また、Goのように、継承を全くサポートしていない言語も存在する。

開放/閉鎖原則は、クラスやメソッドは「拡張に対しては開放的であるが、変更に対しては閉鎖的であるべき」という原則を提唱している。

委譲もまた、継承の代わりに利用できる言語機能である。

ポリモーフィズム

[編集]

サブタイピングポリモーフィズムの一形態)では、呼び出すコードが、サポートされている階層のどのクラスを操作しているのか (親クラスなのかその子孫なのか)という詳細には関知しないことが可能である。一方、継承階層内のオブジェクト間では、同じ操作名でも挙動が異なる場合がある。

例えば、Circle型とSquare型のオブジェクトが、Shapeという共通のクラスから派生している場合、Shapeの各型のDraw関数は、それぞれの描画に必要な機能を実装しているが、呼び出しのコードは、描画されるShapeが特定の型であるかどうかには無関心でいられる。

これもまた、クラス階層からコードを引き離して単純化し、強力な関心の分離を可能にする抽象化の一種である。

オープンな再帰

[編集]

オープンな再帰[20]をサポートする言語では、オブジェクトのメソッドは同じオブジェクト上の他のメソッドや自分自身を呼び出すことができる。通常はthisselfと呼ばれる特別な変数やキーワードを使用して呼び出しをするのが一般的であるが、この変数は「遅延結合」であり、あるクラスで定義されたメソッドが、そのサブクラスで後から定義された別のメソッドを呼び出すことができる。

デザインパターン

[編集]

継承とBehavioral subtyping

[編集]

継承は意味論的には is-a の関係を作るため、サブクラスからインスタンス化されたオブジェクトは、スーパークラスからインスタンス化されたオブジェクトの代わりに、常に安全に使用できる、と推測するのは直感的ではあるが、この直観は、ほとんどのOOPL、特にミュータブルなオブジェクトを許可している言語では誤りである。 (ミュータブルなオブジェクトを持つ)OOPLの型検査器によって強制される部分型付け (部分型多相/サブタイピング多相)では、いかなる状況でも、振る舞いにおける部分型付け (Behavioral subtyping) は保証することはできない。 Behavioral subtyping は一般に決定不能であり、プログラム (コンパイラ)では実装できない。クラスやオブジェクトの階層は、文法間違いでは検出できない使い方がされる可能性を考慮に入れて、慎重に設計する必要がある。この問題はリスコフの置換原則としても知られている。

GoFデザインパターン

[編集]

オブジェクト指向とデータベース

[編集]

OOPL と関係データベース管理システム (RDBMS) は、どちらも今日のソフトウェアとして非常に一般的であるが、双方を接続する場合、関係データベースは、オブジェクトを直接格納しないため (ただし、今日ではこれに近しい拡張機能を持つ RDBMS も存在する)、この二つの世界を橋渡しすることが一般的な需要として擡頭した。アクセス方法やデータパターンを OOPL と RDB との間で橋渡しする際の問題は、オブジェクト-リレーションのインピーダンスミスマッチと呼ばれている。 この問題に対処するためのアプローチはいくつかある。欠点のない一般的な解決策といえるものはない[21]が、代表的なものとして、オブジェクト関係マッピング(ORM)があり、Visual FoxProなどのIDE言語や、Java Data Objects、Ruby on RailsActive Recordなどのライブラリが存在する。

また、RDBMS を代替するオブジェクトデータベースも存在するが、技術的にも商業的にも RDBMS ほど広く成功は収めていない。

OOPと制御構造

[編集]

OOPは、ソースコードのコードの再利用性ソフトウェアの保守性を高めるよう発展してきたが[22] 、ある時期までは制御フローの透過的な表現については、あまり省みられることもなく、コンパイラが任意に処理すれば良いと考えられてきた。しかし、OOPでの実現にはある種の困難を伴うものの、並列ハードウェアやマルチスレッドコーディングの重要性が増すにつれ透過的な制御フローの開発は重要になってきている[23][24][25][26]

責任駆動設計 対 データ駆動設計

[編集]

責任駆動設計では、クラスは、共有する情報とそれを扱う責務という観点から定義されるべきであるとし、クラス定義 (とその利用者)の契約として設計する。Wirfs-BrockとWilkersonは、責任駆動設計と対比して、データ駆動設計は、クラスが保持すべきデータ構造のみを中心に定義されるとし、責任駆動型の設計が望ましいとしている[27]

SOLID、GRASPのガイドライン

[編集]

SOLIDのガイドラインは、プログラミングにおける五つの実践の頭文字をとった語呂合わせであり、マイケル・C・フェザーズ[28]が考案し提唱したものである

GRASP(General Responsibility Assignment Software Patterns)は、クレーグ・ラーマンが提唱したもう一つガイドラインである。

形式意味論

[編集]

脚注

[編集]

注釈

[編集]
  1. ^ 1995年6月 Visual FoxPro 3.0, FoxPro は手続き型言語からオブジェクト指向言語へと進化した。Visual FoxPro 3.0では、データベースコンテナ、シームレスなクライアント/サーバー機能、ActiveXのサポート、OLEオートメーションとヌルのサポートが導入された。Summary of Fox releases

出典

[編集]
  1. ^ Kindler & Krivy 2011.
  2. ^ Lewis & Loftus 2008, §1.6 "Object-Oriented Programming".
  3. ^ a b Meaning 2003.
  4. ^ LISP 1 Programmers Manual 1960, p. 88f.
  5. ^ LISP 1.5 Programmers Manual 1962, p. 105.
  6. ^ Sutherland 1963.
  7. ^ a b Nygaard & Dahl 1978.
  8. ^ a b c Holmevik 1994.
  9. ^ Dahl 2004.
  10. ^ a b Meyer 2009.
  11. ^ Kay 1993.
  12. ^ FoxProの歴史: Foxprohistory.org
  13. ^ 1995年のVisual FoxPro 3.0 レビュー/ガイド: DFpug.de
  14. ^ Khurana, Rohit (1 November 2009). Object Oriented Programming with C++, 1E. ISBN 978-81-259-2532-3. https://books.google.com/books?id=MHmqfSBTXsAC&pg=PA16 
  15. ^ マイナビTECH+: Delphiがトップ20位から脱落: 「Delphiは2001年6月にトップ20位入りを果たし、2000年代初頭には最も人気のある統合開発環境として広く使用されていた。」[1]
  16. ^ Wirth, Niklaus. From Modula to Oberon and the programming language Oberon (Report). ETH Technical Reports D-INFK. Vol. Band 82. Wiley.
  17. ^ 共通型システム|Microsoft Docs [2]
  18. ^ Booch, Grady (1986). Software Engineering with Ada. Addison Wesley. p. 220. ISBN 978-0-8053-0608-8. https://en.wikiquote.org/wiki/Grady_Booch. "Perhaps the greatest strength of an object-oriented approach to development is that it offers a mechanism that captures a model of the real world." 
  19. ^ Jacobsen, Ivar; Magnus Christerson; Patrik Jonsson; Gunnar Overgaard (1992). Object Oriented Software Engineering. Addison-Wesley ACM Press. pp. 43–69. ISBN 978-0-201-54435-0. https://archive.org/details/objectorientedso00jaco/page/43 
  20. ^ 『型システム入門』オーム社、2013年、185頁。  18.10 selfを介したオープンな再帰
  21. ^ Neward, Ted (26 June 2006). “The Vietnam of Computer Science”. Interoperability Happens. 4 July 2006時点のオリジナルよりアーカイブ。2 June 2010閲覧。
  22. ^ Ambler, Scott (1 January 1998). “A Realistic Look at Object-Oriented Reuse”. drdobbs.com. 4 July 2010閲覧。
  23. ^ Shelly, Asaf (22 August 2008). “Flaws of Object Oriented Modeling”. Intel Software Network. 4 July 2010閲覧。
  24. ^ James, Justin (1 October 2007). “Multithreading is a verb not a noun”. techrepublic.com. 10 October 2007時点のオリジナルよりアーカイブ。4 July 2010閲覧。
  25. ^ Shelly, Asaf (22 August 2008). “HOW TO: Multicore Programming (Multiprocessing) Visual C++ Class Design Guidelines, Member Functions”. support.microsoft.com. 4 July 2010閲覧。
  26. ^ Robert Harper (17 April 2011). “Some thoughts on teaching FP”. Existential Type Blog. 5 December 2011閲覧。
  27. ^ Wirfs-Brock, Rebecca; Wilkerson, Brian (1989). “Object-Oriented Design: A Responsibility-Driven Approach”. ACM SIGPLAN Notices 24 (10): 74. doi:10.1145/74878.74885. 
  28. ^ https://wiki.c2.com/?MichaelFeathers

出典

[編集]

関連項目

[編集]

システム

[編集]

モデリング言語

[編集]