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

削除された内容 追加された内容
編集の要約なし
(同じ利用者による、間の24版が非表示)
1行目:
{{複数の問題
|独自研究=2018年2月
|正確性=2019年2月
|出典の明記=2019年2月
}}
 
{{プログラミング言語|index=おふしえくとしこうふろくらみんく}}
[[ファイル:History of object-oriented programming languages.svg|サムネイル|OOP言語の系譜(水色がOOP)|代替文=|280x280ピクセル]]
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|''object-oriented programming''}}; 、略語:OOP)は、[[オブジェクト指向]]の[[プログラミングパラダイム|考え方]]<ref>コンピュータ・プログラミングのパラダイムについては『新しいプログラミング・パラダイム』などを参照: http://www.kyoritsu-pub.co.jp/bookdetail/9784320024939</ref>を取り入れた[[プログラミング (コンピュータ)|コンピュータ・プログラミング]]法である。プログラムを「[[オブジェクト (プログラミング)|オブジェクト]]」の集合体して構築し、オブジェクト大まかに言うとデータ(状態[[変数 (プログラミング)|変数]]または[[プロパティ (プログラミング)|プロパティ]]を主し、コード(動作[[関数 (プログラミング)|関数]]または[[メソッド (計算機科学)|メソッド]]を従として構成され、無数オブジェクトが相互に作用しうようにして任意の処理が実行される。オブジェクトとは対象物を意味し、CPU演算処理(コード)が参照ないし変動の対象とすデータ全般と考える事出来る。「ど、そ詳細データを扱うか」でついて様々く「データ解釈どの様に扱われ存在すか」を念頭。OOP置いて基づくプログラムはこの[[オブジェクト (プログラミング)|オブジェクト]]の集合中心にして組み立てられ手法がOOPという事になるが、その実装スタイルもまた千差万別である。
 
OOPの成り立ちにもまた諸説ある。オブジェクト指向プログラミングという言葉自体は、計算機科学者[[アラン・ケイ]]が1972年に[[Smalltalk]]の言語設計を説明する中で初めて生み出されている。なお、データとコードの複合体である[[オブジェクト (プログラミング)|オブジェクト]]という用語を確立したのは1967年公開の[[Simula|Simula67]]であった。[[Simula|Simula67]]の[[クラス (コンピュータ)|クラス]]と[[オブジェクト (プログラミング)|オブジェクト]]の設計及び用法は[[手続き型プログラミング]]の機能拡張に近いものであったが、こちらもOOPの草分けと見なされるようになった。[[Smalltalk]]のプログラム内のあらゆる要素をオブジェクトとして扱い、[[メッセージパッシング]]で相互作用させる本来の意味でのオブジェクト指向設計は、哲学的かつ理論偏重のきらいがあったので実践面ではさほど広まらなかった。1983年に公開された[[C++]]が契機となり、OOPはまた違った角度から注目されるようになった。最終的にこの[[C++]]の設計スタイルが物議を醸しながらもOOPの主流となるに到り、同時にOOPの三大原則とされる[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム|多態性]]の[[プログラミングパラダイム]]が確立されている。
オブジェクト指向プログラミングは、ソフトウェアの大規模化に伴い、より効率的な開発手法が模索される中で1960年代から70年代にかけて確立された。OOP言語は歴史的にクラス仕様を中心とする[[Simula]]系統と、メッセージ仕様を主体とする[[Smalltalk]]系統に分けられるが、後に[[C++]]や[[Java]]などの言語の派生元となった前者が主流となった。この前者のオブジェクト指向が示す「[[カプセル化]]」「[[継承 (プログラミング)|継承]]」「[[ポリモーフィズム|多態性]]」の三大原則を備えていれば、OOP言語であると見なされる。
 
== 特徴 ==
プログラミングパラダイムとしてのオブジェクト指向の確立は紆余曲折を経ており(後述)その詳細の解釈も様々であるが、一定の枠組みとなる三つの原則仕様(''fundamental principle'')が存在する。この三原則に従った言語仕様を総体的または部分的に備えたプログラミング言語がオブジェクト指向準拠と判別される。1~3はいわゆるOOPの三大原則とされるものであり、[[C++]]を契機にして確立された。4はオブジェクト指向プログラミングという用語の発端となった[[Smalltalk]]設計の主軸であるが、現在では亜流となっている。
OOPの基本原則(''fundamental principle'')仕様は以下の通りである。1~3は[[Simula]]系統であるクラス主体(''classes-principled'')OOPの三大原則となっている。4は[[Smalltalk]]系統であるメッセージ主体(''messaging-principled'')OOPの主要原則とされる。
 
#[[カプセル化]] (''encapsulation'') - <small>内部隠蔽</small>
#[[継承 (プログラミング)|継承]] (''inheritance'')
#[[ポリモーフィズム|多態性]] (''polymorphism'')
#*アドホック多態性(''ad hoc polymorphism'')
#*[[多重定義]] (''overloading'') - <small>演算子オーバーローディングも含む</small>
#**[[多重定義|関数オーバーロード]](''function overloading'')
#*{{仮リンク|パラメータ多相|en|Parametric polymorphism}} (''parametric polymorphism'') - <small>[[ジェネリックプログラミング]]</small>
#**[[多重定義|演算子オーバーロード]](''operator overloading'')
#*[[派生型|派生型付け]] (''subtyping'') - <small>動的なもののみ</small>
#*パラメータ多態性(''parameter polymorphism'')
#*[[仮想関数]] (''virtual function'')
#**[[ジェネリックプログラミング|ジェネリック関数]](''generic function'')
#*[[多重ディスパッチ]] (''multiple dispatch'')
#**[[メッセー (コンピュータ)|メェネリセージパッシクプログラミング]] (''messagegeneric passingprogramming'')
#*[[派生型|サブタイプ多態性]](''subtyping'')
#**[[仮想関数]] (''virtual function'')
#**動的ディスパッチ(''dynamic dispatch'')
#**[[ダブルディスパッチ]](''double dispatch'')
#**[[多重ディスパッチ]] (''multiple dispatch'')
#[[メッセージ (コンピュータ)|メッセージパッシング]](''message passing'')
 
; カプセル化
 
従来の手続き型プログラミング環境では、動作を定義する'''コード'''(関数)が、状態を表現する'''データ'''(変数)を扱う形でプログラムを記述するのが一般的だったが、開発規模の拡大に伴い解決の難しいソフトウェア・バグ原因の大半はデータの予期せぬ変動各データ間の不整合である事が経験則で知られるようになって来た。そこでデータを中心にしてプログラムを組み立てようとする考え方が生まれ、その目的に沿うものとしてデータそれに付随するコード群をまとめた'''の複合体であるオブジェクト'''というプログラミング概念に白羽の矢編み出さ立てられた。従来の「コードの為オブジェクト内のデータ」と基本的「データの為同じオブジェクト内のコード」としだけが参照ま変動可能とする仕組みが考案されこれがカプセル化と呼ばれた。データを変動させたコード位置の把握を容易に特定出来るようにしてバグ発見に繋げる為であった。この目的沿って特定の、各データを扱えにアクセス出来るコード範囲を厳密に定めた'''内部隠蔽'''カプセル化の機能は、範囲外アクセス範囲外からのデータ参照とコード呼出をコンパイルレベルで禁止して想定外のデータ変動をもたらす人的ミスを減らした。また、データを変動させるコードを呼び出すそのまたコード位置の把握も芋蔓式に必要となったのでコードにもアクセス可能範囲が定められる様になり、更にアクセス範囲の広さにも段階が設けられたので特定の外部をも含んだ柔軟な内部隠蔽の設計が可能となった。
 
; 継承
 
また、プログラム内の膨大な数のデータは通常グループ化(構造体)されて扱われていたが、複数の構造体間にまたがる共通のデータ集合が数出現しく目に付くようになり、その冗長と整合の頻雑さの問題が浮き彫りとなっていた。これを解決する為にOOPは、構造体=オブジェクトを複数の'''階層要素'''に分け、共通のデータ集合を親階層とし、派生する子階層に親階層の参照アドレスを持たせて連結する構造としが考案された。A階層から成る親オブジェクトから派生した子オブジェクトはA+B階層として構成され、これが'''継承'''と呼ばれた。コードから参照されたデータがB階層に無い時は、次のA階層に有るか探す仕組みとなり、この連鎖によって傍からは一つのオブジェクトとして存在した。なお、派生クラスで任意のデータとメソッド機能を追加出来る継承の機能、工夫次第で従来コードの再利用性を高めるとも見なさ考えられたが、深い継承がもたらす構成把握の難化がネックとなっ問題視されてほぼ否定される様になり、た。これはクラスライブラリ使用の範疇内に留まっている。{{いつ範囲|date=2019年2月|現在}}では深い継承は回避倦厭される様になり、代わりに共通仮想メソッド呼出テーブル(Javaの''interface''など)を実装させる横に長い継承が主流となっ重視されている。また、Simula系統クラスメカニズムをベースとするOOP言語では多態性を実現する為の重要な手段として用いられている。
 
; 多態性
 
アドホック多態性は単にソースコードの記述を一部自動化するものである。'''関数オーバーロード'''は引数の並び方によって同じ名前のメソッドをコンパイル時に自動的に差別化する機能である。'''演算子オーバーロード'''は、扱う数値の型に従って宣言された演算記号を関数名と見なすようにし、単項演算子なら右の数値を第一引数とし、二項演算子なら左右の数値をそれぞれ第一第二引数として関数呼び出しのコードが生成されるという仕組みだった。これらは静的な多態性とされる。
様々なオブジェクトタイプ(型)が扱われるソースコード記述の頻雑性を回避する為に、呼出引数の型に応じたメソッドをコンパイル時に選択する'''多重定義'''と、型引数に応じたクラスorメソッドをコンパイル時に生成する'''パラメータ多相'''の機能が備えられた。これらは静的な多態性(''static polymorphism'')とも呼ばれる。動的な多態性(''dynamic polymorphism'')としては、特定の場面で扱われるオブジェクト群が共通して持つ階層要素の部分で一括りにして順次処理を行い、条件分岐をより柔軟かつ簡素にする目的で、特定の階層のコードの存在を抽象化して呼び出しポイントとし、オブジェクト共通の階層要素が持つ呼び出しポイントから、それぞれ異なる派生先階層の実装コードを呼び出すという'''仮想関数'''の仕組みが実装された。また、オブジェクトが特定の階層要素を持つかチェックした上でその階層に準じた動的な'''派生型付け'''を行い、その型変化させたオブジェクトを引数にした多重定義と仮想関数呼び出しの併せ技である'''多重ディスパッチ'''の機能も編み出され、データがコードを制御するというOOPの理念は明確に表現された。
 
パラメータ多態性もソースコードの記述を一部自動化するものである。関数内またはクラス内の型指定部分をワイルドカードにして宣言しておき、ソースコード内で関数またはクラスが実装記述されると、その具体的な型指定を関数内またはクラス内のワイルドカードに当てはめたコード部分がコンパイル時に自動生成されるという機能だった。前者は'''ジェネリック関数'''と呼ばれ、後者はより広い範囲を扱う事から'''ジェネリックプログラミング'''と名付けられた。これらも静的な多態性に位置付けられている。
 
サブタイプ多態性は動的なものである。最も初期のOOPであるSimula67は、シミュレーション内で扱う多種多様なオブジェクトを継承によって体系化したが、コード部分の細かな違いは共通スーパークラスに属する共通プロシージャ内の分岐フローで処理していた。サブクラスの数だけ分岐構文が増える頻雑さを解消する為に、共通プロシージャをただの住所テーブルにしてサブクラスの実装時に同名プロシージャのアドレスを収納させ、呼び出し時はそのアドレスへジャンプするという機能が考案され、これが'''仮想関数'''となった。'''動的ディスパッチ'''はSmalltalkのオブジェクト設計に由来するものであり、その実装の仕方は様々でやや曖昧な仕様でもある。メッセージを受け取ったレシーバーがオブジェクト内部で動的な状態に従い動的な処理を行って結果を返すというランタイム環境上のプロセスが後に動的ディスパッチのカテゴリで括られた。遠隔プロセスを扱うリモートメソッドのシステムも動的ディスパッチに該当するものである。'''多重ディスパッチ'''は動的な関数オーバーロードに近いものである。関数コール時または関数ブロック内で、それぞれの引数が動的に型審査されて型変化(''dynamic casting'')された後に、その引数パターンに対応した同名関数または分岐ルーチンに処理が移行されるという動的変化プロセスを指した。'''ダブルディスパッチ'''は多重ディスパッチの亜流またはその派生物であり、二通りの考え方がある。動的型審査および型変化されるBオブジェクトを単一引数にしてAオブジェクトの仮想関数メソッドを呼び出す形態と、多重ディスパッチに用いる引数を二つに限定した形態である。いずれも実行時状態に応じた動的変化プロセスとなった。これは主にデータ集合を対象にして分類、解析、作用といった処理を連続的または再帰的に行うアルゴリズムで用いられた。
 
; メッセージパッシング
 
上述の三つの機能と異なり、メッセージパッシングこれオブジェクト指向そ従来ものと肩を並べるパラダイムであり、オブジェクト指向が示す機能の大半を結果的に実現出来る「[[タデータ|メタ]]」的な土台となった。これは従来の付きサブルーチン呼出とリタン値形態やり取り変え別の視点から再解釈しのであり、基本はバイトデータ('''メッセージ''')の送受信でセレクタ(メソッド名とパラメータ値および、そしてリターン値をやり取りする仕組みだった。オブジェクトのレシーバー関数(代表メソッド)引数として渡されたメッセージを読み込み解釈し、オブジェクト内部でそれに準じた処理を行い、結果をリターンした。レシパラメタとリタの仕組みは結果的に「内部隠蔽」を実現出来ン値もまオブジェクト内部だったの、リターン値をメッセージ内自由自在な処理実装パラメータして後続のオブジェクトへ送事もでき、そのリターンはこれも結果的「多態性」また別のメッセージ実現送る事も出来た。この実装をサポSmalltalk設計では真偽値、数値、コドブロックもオブジェクする為となったので、真偽値または数値「[[リフ対して規定の予約語(セレクション (情報工学)|リタ)と併せたコードブロックをメッセージとして送る事で条件分岐や反復処理といった制御ローを表現出来た。オブジェション]]」トを次々とメッセージとして送る機能が備えられは順次処理となった。メッセージパッシングがもたらす変幻自在なメソッドの選択実行は、通信網オブジェクトにオブジェクト介し引き合わせ他サ、双方に関連した手続きまたは制御フロバー上で実行を発生れていビスプロセスチンワーク自身のソフトウェアの一部と意味して扱う様おり、この連鎖的かつ再帰的事も可能に繰り返がプログラム全体の流れとなった。あらゆる手法に応用出来るメッセージこの斬新なッシンラダイムを実際のプロラムの形にする為に比較的緻密な設計が要求されまたパターン化されたプロセスにおいても柔軟さを維持する為適用範囲ワンステップ広げ必要とすほどので開発工数と実行CPU負荷増大する欠点もあった。これが倦厭されてOOP設計本質、決してオールマイティに用いありなが広くは支持さず、OOPに対す関心焦点は本来は枝葉の部分あるないが、ソフトウェアモジュール化およびコンポーネント化をよりダイナミッラスのメカニズム、そしてグローバル移る事発展させる潜在力を秘めており、OOPがもたらす実装の拡張性を大きく広げなった。
 
Smalltalkの影響を受けた後継言語においても、あらゆるプログラム要素をメッセージで表現しようとする理論の追求は避けられ、例えば制御フローは制御構文で扱われている。またメッセージングに対する認識もシフトし、オブジェクトの代表となるメソッドがパラメータを受け取り多様な処理と移譲を行ういわゆるレシーバーの仕組み自体がメッセージングそのものと見なされるようになった。そのメカニズムを応用したリモートメソッドを実現するバイトデータの送受信もメッセージパッシングの代表例となった。この様にメッセージパッシング設計の本質は見失われながらも、その側面的仕様は数々のOOP言語に導入されてもいる。
 
== 歴史 ==
58 ⟶ 65行目:
 
== OOP言語一覧 ==
オブジェクト指向を総体的または部分的にサポートする機能を備えたプログラミング言語の公開は、1980年代後半から顕著となった。オブジェクト指向プログラミングOOP言語スタイル分類法複数あるが[[クラス (コンピュータ)|クラス仕様]]Smalltalk中心ルーツとする'''Simula系統'''と、[[メッセージパッシング|メッセージ仕様]]を主体とする'''Smalltalk系統'''二通りに分けら構文が重視さか否かで大別される事が多い前者にはそうでないものがOOP言語の主流となっており「C++」「Java」「C#」「Swift」などが、後者その代表とされる。メッセージパッシングを重視するOOP言語には「Smalltalk」「Objective-C」「SwiftSelf」などがある。言語仕様の中でオブジェクト指向の存在感が比較的高い代表的なプログラミング言語を以下に列げられる。
 
オブジェクト指向プログラミング言語の形態には、オブジェクト指向と他の[[プログラミングパラダイム|パラダイム]]が同居している'''ハイブリッドOOP'''と、オブジェクト指向に基づくコードプロセスだけが許容される'''ピュアOOP'''の双方が存在する。前者には「C++」「Objective-C」「Java」「C#」「Swift」などが、後者には「Smalltalk」「Eiffel」「Self」などがある。
 
言語仕様の中でオブジェクト指向の存在感が比較的高い代表的なプログラミング言語を以下に列挙する。
 
[[Simula|'''Simula 67''']] 1967年
: 1962年に公開された[[Simula]]の後継版であり、[[クラス (コンピュータ)|クラス仕様]]のプログラミング概念を導入した最初の言語である。現実世界の擬似モデルを観測するシミュレーション・プログラム記述制作用に開発されたものでクラスを実メモリに展開したオブジェクトは、その観測対象要素となった。simulaのクラスは、サブルーチン変数と補助プロシージャを加えた機能的小型モジュールに近いものであったが、継承と仮想関数という先進的な設計を備えていた事でOOPの草分けと見なされるようになった。C++、Java、C#に代表される'''クラス主の設計母OOP'''のルーツされるなった
 
'''[[Smalltalk]]''' 19801972
: オブジェクト間の相互作用を担う[[メッセージパッシング|メッセージ仕様]]のプログラミング概念を導入した最初の言語。数値、真偽値から変数、構造体、コードブロック、メタデータまでのあらゆる要素をオブジェクトとする概念を編み出した最初の言語でもある。オブジェクト指向という言葉は、Smalltalk開発者がその言語仕様設計を説明する中で生み出された。'''メッセーオブ主体OOP'''ェクト元祖であり、高度に柔軟基礎的振る舞いを規定する限られた予約語の他は、オブジェクトとメッセージ連携動作やり取りで制御構造を含めたあらゆるプロセスを表現でき出来た。また、専用のランタイム環境上でプログラムを実行する設計を応用して動的な多態性とセキュリティに繋がるモニタリングも実現した。これは後に仮想マシンと呼ばれる専用ランタイム環境も用意となり、JavaやC#に踏襲された。
 
'''[[C++]]''' 1983年
: [[C言語]]にクラス主体OOPに基づく言語仕様デザインを追加したもの。Simulaの影響を強く受けている。[[クラス仕様によっ (コンピュータ)|クラス]]のメカニズムが備えられカプセル化、継承、多態性といったOOP仕様表現実装している。また[[ジェネリックプログラミング|ジェネリクス]]に相当する[[テンプレート (プログラミング)|テンプレート機能]]や[[例外処理]]、演算子オーバーロードを応用した関数オブジェクトなど様々なプログラミングパラダイム備えてい導入された。元がC言語であるため、OOPから逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。
 
'''[[Objective-C]]''' 1984年
:[[C言語]]にメッセージ主体OOPに基づく言語仕様追加OOPデザイン化したもの。こちらはSmalltalkの影響を強く受けているおり、それに準じた[[メッセージパッシング]]と[[リフレクション (情報工学)|リフレクション]]のメカニズムが備えられた。OOP的には前述のC++よりも正統であると見なされた。制御構文が追加され、メッセージプログラミング・パラダイム仕様共存しやや簡素化されるなど実践上の便宜が図られており、Smalltalkよりもコーディングし易くなった。
 
'''[[Object Pascal]]''' 1986年
:[[Pascal]]にクラス主体OOPに基づく言語仕様追加OOPデザイン化したもの。
 
'''[[Eiffel]]''' 1986年
:[[Pascal]]をベースにしてクラス主体OOPに基づく言語仕様とデザイン化し、また[[ジェネリックプログラミング|ジェネリクス]]のパラダイムを追加した。型付けは静的に限られ、非参照データを自動解放する[[ガーベジコレクション|ガーベジコレクタ]]を持ち、多重継承時の問題を回避する仕組みや例外処理など高い堅牢性を備えた。これらは後のJavaやC#の手本となった。
 
'''[[Self]]''' 1987年
: メッセージ主体OOPに分類されパッシングの構文が中心となっている。動的な多態性を重視した言語であり、従来の[[クラスベース]]のオブジェクト設計に対して、システム側が用意したオブジェクトを複製して任意の拡張を施す[[プロトタイプベース]]のデザイン初めて実装した。Smalltalkと同様に専用のランタイム環境で実行されたが、これも実用面では初となる[[実行時コンパイラ]](just(''just-in-time compiler)をcompiler'')の機能が備える専用られて速度面でも画期的なもランタイム環境で実行されとなった。
 
'''[[CLOS]]''' 1988年
:[[Common Lisp]]にメッセージ主体OOPに基づく言語仕様追加OOPデザイン化したもの。
 
'''[[Python]]''' 1990年
: クラス主体OOPに分類される。[[インタプリタ]]式で動作する。言語仕様を簡素化し自動メモリ管理機能を実装して扱いやすく理解しやすいOOPを目指している。後のOOPスクリプト言語の手本となった。
 
'''[[Java]]''' 1995年
:堅牢性と安全性を重視したクラス主体OOPである言語その二つの理念を実現する為に、仮想マシン上の実行、ガーベジコレクタ、例外処理などを採用し、ポインタと直アドレス変数、多重継承ジェネリックプログラミング、演算子オーバーロードなどを破棄した。破棄部分についてはその埋め合わせの仕様設計も備えられているメッセージ主体OOP的設計を表現出来るシリア[[クイゼーショス (コやリフレピュータ)|ションラス]]メカニズムを中心にしたOOPであるが、々なプログラミングパラダイム導入追加されている。非常に整えられたハイブリッドOOP言語である。
 
'''[[Delphi]]''' 1995年
:クラス主体OOPに分類される。[[Object Pascal]]を発展させたもので、データベースの操作プログラム開発などを主な用途とした。一時期Javaの対抗馬となった。
 
'''[[Ruby]]''' 1995年
: クラス主体OOPに分類デザインされスクリプト言語である。[[インタプリタ]]式で動作する。スクリプトでありながら、クラス、マルチスレッド、例外処理、そして[[ソフトウェアコンポーネント]](モジュール)を扱える[[Mixin]]といった利便性と汎用性の高い機能も備えている。
 
'''[[JavaScript]]''' 1996年
:[[ウェブアプリケーション]]開発を主な目的とするOOPスクリプト言語。主に[[プロトタイプベース]]でオブジェクトを扱う事でコーディングを簡便にしている。クラス主体OOPに分類される。[[ECMAScript]]として標準化されている。ECMAScript 2015ではクラス構文をサポートするようになった。
 
[[C Sharp|'''C#''']] 2000年
:[[Java]]を強く意識して開発されたクラス主体OOP言語。[[.NET Framework]]などの[[共通言語基盤]]上で実行される。Javaと同等または部分的に拡張させた仕様スタイルを持ち、こちらもよく整えられたハイブリッドOOP言語として知られる。
[[Microsoft Visual Basic .NET|'''Visual Basic.NET''']] 2002年
: 従来の[[Microsoft Visual Basic|Visual Basic]]の構文ベースにOOPデザイン化つつ、クラス主体OOPに基づいて言語仕様が改変されているたもの。[[.NET Framework]]などの[[共通言語基盤]]上で実行される。
 
'''[[Ceylon]]''' 2011年
:[[Java]]を元に開発され、その長所と短所を見直しつつ再設計されたOOP言語。Javaの改造版である。また[[JavaScript]]にもコンバートできる。
 
'''[[Kotlin]]''' 2011年
:[[Javaバイトコード]]を出力し、[[Java仮想マシン]]上で動作するJVM互換のOOP言語。関数型プログラミング言語由来の機能を持つ。
[[Swift (プログラミング言語)|'''Swift''']] 2014年
 
:[[Objective-C]]の後継言語。クラス主体OOPとメッセージ主体OOPの中間に位置する。関数型プログラミング言語由来の機能など他のパラダイムも併せ持っている。
:高度に整えられたマルチパラダイムプログラミング言語。クラスのメカニズムをベースにしたオブジェクト指向的言語仕様も導入されている。
 
== OOP言語の仕組み ==
130 ⟶ 133行目:
これらをどのように言語の要素として提供し、どのような[[機械語]]コードで実現するかによって様々な[[オブジェクト指向プログラミング言語]]のバリエーションが生まれる。以下、オブジェクト指向プログラミング言語が提供する様々な要素が上記の仕組みをどのように実現しているかについて概観する。
 
=== オブジェクトの概念と実 ===
'''[[オブジェクト (プログラミング)|オブジェクト]]''' ({{Lang|en|object}}) はオブジェクト指向プログラミングの中心となる'''概念'''であり、この概念を'''実際'''にどう実現するかは[[オブジェクト指向プログラミング言語]]により異なる。
 
139 ⟶ 142行目:
* 概念的には コードとデータが一つになっている。
 
==== オブジェクト概念の実現方法装構造 ====
実際のプログラムでは、全てのオブジェクトが互いに全く異なった存在ではなくオブジェクトは種類に分けることが出来る。
 
154 ⟶ 157行目:
もう一つは同一種類のオブジェクトでもそれぞれ異なる部分、典型的には各オブジェクトが保持するデータ群である。
 
==== クラスオブジェクト ====
動的型付けを採用するオブジェクト指向言語の多くは、クラスより生成するインスタンスの他に[[メタクラス]]という機能を持ちクラス自体をオブジェクトとして扱うことが出来る。このためオブジェクトには、インスタンスオブジェクトとクラスオブジェクトという2種類のオブジェクトが存在する。Java等クラスオブジェクトを持たない言語の文化圏では、インスタンスオブジェクトとオブジェクトを混同して説明される事があるが、Objective-CやPython、Ruby等、インスタンスオブジェクトとクラスオブジェクトが別であるオブジェクト指向言語では区別して説明される。<ref>Objective-Cプログラミ
ング言語[https://developer.apple.com/jp/devcenter/ios/library/documentation/ObjC.pdf]</ref>
160 ⟶ 163行目:
<ref>クラス/メソッドの定義 (Ruby manual) [http://www.ruby-lang.org/ja/old-man/html/_A5AFA5E9A5B9A1BFA5E1A5BDA5C3A5C9A4CEC4EAB5C1.html]</ref>元々はSmalltalkから始まった用語である。
 
==== メッセプライベトデータ処理扱い ====
{{seealso|this (プログラミング)}}
そしてあるオブジェクトOにメッセージを配送し適切なメッセージ処理コード(振る舞い)を呼び出す際には、まず対象となるオブジェクトOについて共通部分の格納場所を見つけて適切なコードを選び出し、次にそのコードに対して処理対象となるオブジェクトO固有のデータの所在を示す'''オブジェクトID'''を渡すようになっている。
179 ⟶ 182行目:
 
最も普及している[[クラスベース]]の言語では、共通部分はオブジェクトの種類を表現するクラスに保持され、各オブジェクトは固有データと共にそのクラスのIDを保持する。そしてオブジェクトに送られるメッセージはその送り先オブジェクトにあるクラスのIDからクラスを見つけ、その中からメッセージを処理するコードを見つけ出し、処理対象となっているオブジェクトのIDを付してそのコードを呼び出す仕組みになっている。
 
==== コンポジション ====
'''コンポジション'''は、複数のオブジェクトがある一つのオブジェクトの構成要素となっている巨大なオブジェクト群をいう。コンポジションのもとにあるオブジェクトは同一の生存期間を持ち、一つの巨大な仮想オブジェクトの構成部品として機能する。
 
=== メッセージ ===
207 ⟶ 213行目:
多くの言語でクラスは言語の要素として直接実現されているが、これは実行効率のためであり、そのように実現することが必須というわけではない。実際、各クラスをそれぞれオブジェクトとして提供する言語も存在する(例:[[Smalltalk]])。このような言語ではある種の'''[[リフレクション (情報工学)|リフレクション]]''' (reflection) が可能となる。即ち必要があればプログラムで実行時にクラスの動作を変更することが可能である。これは非常に大きな柔軟性を提供するが、[[処理系|言語処理系]]による最適化が難しいため実行効率は低下することが多い。{{いつ範囲|date=2019年2月|近年}}では柔軟性と効率性を両立させるために基本的に言語要素としてクラスを提供した上で、リフレクション機能が必要なプログラムに対しては必要に応じて各クラスに対応するクラス・オブジェクトをプログラムが獲得できるようにしている言語が現れてきている。(例:JavaのリフレクションAPI)
 
==== インスプロトンスイプベース ====
{{main|プロトタイプベース}}
クラスは非常に多くのオブジェクト指向プログラミング言語で提供されている機能ではあるが、オブジェクト指向プログラミング言語に必須の機能というわけではない。実際にオブジェクトの管理や、データ・メンバや[[メソッド (計算機科学)|メソッド]]の記述、[[継承 (プログラミング)|継承]]に際してクラスという仕組みに依存せずに、もしくはクラスという仕組み自体を持たずに別の手段でこれらを実現している言語も存在する。このような言語を'''[[プロトタイプベース|インスタンスベース]]''' (''{{Lang|en|instance-based}}'')、'''オブジェクトベース''' (''object-based'') あるいは'''プロトタイプベース''' (''{{Lang|en|prototype-based}}'') のオブジェクト指向プログラミング言語と呼ぶ。インスタンスベースまたはそれに類するオブジェクト指向プログラミング言語には以下のようなものがある:
245 ⟶ 251行目:
'''[[メソッド (計算機科学)|メソッド]]''' ({{Lang|en|method}}) は特定の種類のメッセージの処理方法を記述したものである。メソッドも[[メソッド (計算機科学)#インスタンスメソッド|インスタンス・メソッド]]と[[メソッド (計算機科学)#静的メソッド|クラス・メソッド]]の2種にできる。インスタンス・メソッドはそのクラスの各インスタンスオブジェクトを操作し、クラス・メソッドはクラスオブジェクトを操作する。メソッドとの集まりはそのクラスのオブジェクトが処理可能なメッセージのカタログの機能を果たす。
 
一例として、[[C++]]ではメソッドは'''メンバ関数''' ({{Lang|en|member function}}) や'''関数メンバ''' (function member) と呼ばれる。これはC++が[[グローバル関数]]との区別をつけることと、クラスを[[抽象データ型]]の拡張と位置づけ、非メッセージメタファな言語思想を持っている為である。これら言語ではメソッドをオブジェクト(=クラスやインスタンス)の持ち物として捉えず、クラスに定義された機能要素であると考える。メッセージメタファを否定するため、同時にメッセージを実行するメソッド(手法)ではありえない。
==== 他言語と比較したC++のメソッド ====
[[C++]]ではメソッドは'''メンバ関数''' ({{Lang|en|member function}}) や'''関数メンバ''' (function member) と呼ばれる。これはC++が[[グローバル関数]]との区別をつけることと、クラスを[[抽象データ型]]の拡張と位置づけ、非メッセージメタファな言語思想を持っている為である。これら言語ではメソッドをオブジェクト(=クラスやインスタンス)の持ち物として捉えず、クラスに定義された機能要素であると考える。メッセージメタファを否定するため、同時にメッセージを実行するメソッド(手法)ではありえない。
 
==== クラスメソッド ====
279 ⟶ 284行目:
C++やJavaなどでは、コンストラクタはクラスと同じ名前を持ち、戻り値を持たないメソッドとして定義される。C++では一部のコンストラクタは[[型変換演算子]]として、また[[暗黙の型変換]]にも利用される。
 
=== ガベージコレクションとメモリコンパクション ===
オブジェクト指向プログラミング言語では、オブジェクトへの[[参照 (情報工学)|参照]]や[[ポインタ (プログラミング)|ポインタ]]が多用される。そのため、オブジェクトの[[メモリ]]への割り当てと破棄に関して、[[ガベージコレクション]]による自動管理機能を備えているものが多い。ただし、すべての言語が備えているわけではない。例えば、C++はガベージコレクションを備えていない。
 
=== アクセスコントロール ===
オブジェクト指向プログラミングにおいて、[[オブジェクト (プログラミング)|オブジェクト]]は、[[カプセル化]]されておりブラックボックスである。したがって、処理するメッセージのカタログ、つまりインタフェースだけが利用者に公開され、内部の詳細は隠されるのが基本である。しかし、あるクラスのインスタンスの内部だけで利用されるメソッドまで公開してしまうと、利用者にとって煩雑である。また、定数データ・メンバのようなものは一々メソッドでアクセスするようにせず公開してしまっても、カプセル化の利点は失われず効率的でもある。そこで、オブジェクトを定義するプログラマが各データ・メンバやメソッドについて公開・非公開を設定できる機能を用意している言語は多い。
 
291 ⟶ 296行目:
なお、public、private、protectedというキーワードは、多くのプログラミング言語で用いられているが、その示す意味は言語ごとに差異があるため、注意が必要である。
 
=== コンポジション脚注 ===
'''コンポジション'''は、複数のオブジェクトがある一つのオブジェクトの構成要素となっている巨大なオブジェクト群をいう。コンポジションのもとにあるオブジェクトは同一の生存期間を持ち、一つの巨大な仮想オブジェクトの構成部品として機能する。
 
== 脚注 ==
{{脚注ヘルプ}}
{{Reflist}}