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

削除された内容 追加された内容
→‎継承: 誤字修正
タグ: モバイル編集 モバイルウェブ編集
(同じ利用者による、間の2版が非表示)
9行目:
'''オブジェクト指向プログラミング'''(オブジェクトしこうプログラミング、{{Lang-en-short|''object-oriented programming''}}、略語:OOP)とは、互いに密接な関連性を持つ[[変数 (プログラミング)|データ]]と[[メソッド (計算機科学)|メソッド]]をひとつにまとめて[[オブジェクト (プログラミング)|オブジェクト]]とし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定義と、それらオブジェクトを相互に作用させる様々なプロセスの設定を通して、プログラム全体を構築するソフトウェア開発手法である。
 
'''[[オブジェクト指向]]'''という用語自体は、計算機科学者[[アラン・ケイ]]によって生み出されている。1962年公開の言語「[[Simula]]」にインスパイアされたケイが咄嗟に口にしたとされるこの造語は、彼が1972年から開発公開を始めた「[[Smalltalk]]」の言語設計を説明する中で発信されて1981年頃から知名度を得た。しかしケイが示したオブジェクト指向の要点である[[メッセージパッシング]]の考え方はさほど認知される事はなく、代わりに[[クラス (コンピュータ)|クラス]]と[[オブジェクト (プログラミング)|オブジェクト]]という仕組みを注目させるだけに留まっている。同時にケイの手から離れたオブジェクト指向は[[抽象データ型]]を中心にした解釈へと推移していき、1983年に計算機科学者[[ビャーネ・ストロヴストルップ]]が公開した「[[C++]]」が好評を博したことで、オブジェクト指向に対する世間の理解は「[[C++]]」とそのモデルの「[[Simula|Simula 67]]」のスタイルで定着した。それに基づいて[[カプセル化]]、[[継承 (プログラミング)|継承]]、[[ポリモーフィズム|多態性]]といった考え方も後に確立されている
 
== 特徴 ==
16行目:
#[[カプセル化]](''encapsulation'')
#[[継承 (プログラミング)|継承]](''inheritance'')
#[[ポリモーフィズム|多態性]](''polymorphism'')
#[[メッセージ (コンピュータ)|メッセージパッシング]](''message passing'')
 
23行目:
 
=== 継承 ===
既存オブジェクトのデータ構成とメソッド構成を引き継いで、新しい派生オブジェクトを定義する仕組みが継承と呼ばれる。引き継ぐ際には新たなデータとメソッドを自由に追加できるので、派生オブジェクトの構成は既存要素+追加要素になる。ここでの既存の基底オブジェクトは基底オブジェクトと読み替えられる。基底は親その派生オブジェクトは子とも読み替えられる。継承が重視されるオブジェクトは、型も呼ばして用いられるクラスであることが多い。クラスベースでは、親基底をスーパークラス、派生をサブクラスと呼ぶ。一つのスーパークラスを継承するのは単一継承と呼ばれる。複数のスーパークラスを継承してそれぞれの要素を引き継ぐのは多重継承と呼ばれる。[[統一モデリング言語|UML]]では汎化と特化の関係で表現されている。メソッドの抽象化に焦点を当てた継承の方は{{仮リンク|実装継承|en|Inheritance_(object-oriented_programming)}}などと呼ばれる。UMLでは実現と実装の関係で表現されている。実装継承は特定のオブジェクトたちに共通した振る舞い側面を抜き出して抽象化する仕組みを指し、その抽象オブジェクトは[[インタフェース (抽象型)|インターフェース]]、[[トレイト]]、{{仮リンク|プロトコル(OOP)|en|Protocol (object-oriented programming)|label=プロトコル}}などと呼ばれる。
 
=== 多態性ポリモーフィズム ===
異なる種類のオブジェクトに同一の操作インターフェースを持たせる仕組みがポリモーフィズム(多態性と呼ばれる。オブジェクト指向下の多態性ポリモーフィズムは、クラスの派生関係またはオブジェクトの動的バインディング機能によって、コンパイル時のメソッド名から呼び出されるプロセス内容が実行時に決定されるという仕組みの{{仮リンク|振る舞いサブタイピング|en|Behavioral subtyping}}を指す。これは{{仮リンク|サブタイプ多相|en|Subtyping}}の一種である。その代表格は{{仮リンク|仮想関数(OOP)|en|Virtual function|label=仮想関数}}であり、オブジェクト指向で多態性ポリモーフィズムと言えばこれを指して説明されることが多い。仮想関数は、メソッドが所属するクラスの派生関係のみに焦点を当てた一重ディスパッチであり、スーパークラス抽象メソッドの呼び出しを、それを[[オーバーライド]]したサブクラス実装メソッドの呼び出しにつなげる機能である。一重ディスパッチとはプロセス選択に関与するオブジェクトが一つであることを意味しており、二つ以上の場合は[[多重ディスパッチ]]になる。多重の方はメソッドが属するクラスの派生関係だけでなく、そのメソッドの各引数のクラスの派生関係にも注目した形態であり、各引数は実行時の型判別と[[ダウンキャスト]]されて、その引数型の組み合わせに対応したプロセスを選択する。一重ディスパッチと多重ディスパッチは{{仮リンク|動的ディスパッチ|en|Dynamic dispatch|label=}}という分類用語に包括されており、仮想関数は[[クラスベース]]向けに特化された動的ディスパッチとも定義されている。クラス機構の代わりにプロトタイプ機構を用いる[[プロトタイプベース]]の方では、オブジェクト(フレーム)のメソッド名スロットに当てはめられるメソッド実装の参照が随時切り替えられることにより、そのメソッド名から呼び出されるプロセスが実行時に決定されるという仕組みで広義の振る舞いサブタイピングを表現している。この仕組みも動的ディスパッチという分類用語に包括されており、便宜的にそのまま動的ディスパッチと呼ばれることが多い。
 
=== メッセージパッシング ===
41行目:
 
=== Smalltalkとオブジェクト指向の誕生(1972 - 81) ===
SimulaのProcessおよび67年版からのクラスの仕様は、[[パロアルト研究所]]の計算機科学者[[アラン・ケイ]]によるオブジェクト重視と「メッセージング」というプログラム概念考え方のヒントになった。ケイはプログラム内のあらゆる要素をオブジェクトとして扱い、オブジェクトはメッセージの送受信でコミュニケーションするという独特のプログラム理論を提唱した。メッセーそれには関数適用風の書式を用いたオブェクト同士の多種多様な[[委譲|デリゲーション]]プログラムコードとしても解釈できるデータ列のことであり、を送信してのデータ列を評価(''eval'')することで新たなデータを導出できるという仕組みを意味しなどのアイディアが盛り込まれていた。オブジェクトが送るか受け取ったメッセージは任意のタイミングで評価できるので非同期通信単方向通信(送りっぱなし処理)をも可能にしていた。この発想の背景には[[LISP]]の影響があった。オブジェクトとメッセージングの構想に基づいて開発された「[[Smalltalk]]」はプログラミング言語と[[GUI]]運用環境を併せたものとなり、1972年に[[Alto|ゼロックスAlto]]上で初稼働された。Smalltalkの設計を説明するためにケイが考案した「[[オブジェクト指向]]」という用語はここで初めて発信された。またケイのメッセージング構想は[[MIT]]の計算機科学者[[カール・ヒューイット]]に能動的な[[プロセス代数]]を意識させて、1973年発表の[[アクターモデル]]のヒントにもなっている。しかしデリゲーションの多用とデータ列が常にコード候補として扱われる処理系は、当時のコンピュータには負荷が大きく実用的な速度を得られないという問題にすぐ直面した。Smalltalk-74と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発の[[クラス (コンピュータ)|クラス]]とそれを理論面から形式化した[[抽象データ型]]を中心に解釈されるようになり、それらの考案者がケイの構想とは無関係であったことから、オブジェクト指向の定義はケイの手を離れて独り歩きするようになった。
 
=== C++の開発(1979 - 88) ===
[[Simula]]を研究対象にしていた[[ベル研究所|AT&Tベル研究所]]の計算機科学者[[ビャーネ・ストロヴストルップ]]は、1979年からクラス付きC言語の開発に取り組み、1983年に「[[C++]]」を公開した。C++で実装された[[クラス (コンピュータ)|クラス]]は、Simula譲りの[[継承 (プログラミング)|継承]]と仮想関数に加えて、[[レキシカルスコープ]]の概念をクラス定義とその継承構造に応用したアクセスコントロールを備えていた。C++で確立されたアクセスコントロールはカプセル化の元になったがコードスタイル上ほとんどザル化されており、その理由からストロヴストルップ自身もC++は正しくない(''not just'')オブジェクト指向言語であると明言している。1986年にソフトウェア技術者[[バートランド・メイヤー]]が開発した「[[Eiffel]]」の方は、正しいオブジェクト指向を標榜してクラスのデータ抽象を遵守させるコードスタイルが導入されていた。クラスメンバ(フィーチャー)は属性、手続き、関数の三種構成で、手続きで属性を変更し関数で属性を参照するという形式に限定されており、これは抽象データ型の[[セマンティクス|振る舞い意味論]]に沿った実装であった。アクセスコントロールはC++のアクセス修飾子による段階的レキシカルスコープ定義に対して、自身のクライアントクラスを定義する書式になり、これはモジューラプログラミングの情報隠蔽論に沿った実装であった。C++の仮想関数は延期フィーチャー手続き/関数として実装された。{{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++の人気の方が高まっていた。また、Smalltalk発のメッセージ・メタファを重視しようとする流れの中で、クラスのメソッド呼び出しをオブジェクトにメッセージを送ることになぞらえる考え方が広まった。これは実行時の選択メソッドをメッセージの発送先にする意味合いで、動的/一重/多重ディスパッチの呼称の由来になっている。他方でSmalltalkの仕様に忠実であろうとする動きもあり、1984年に計算機科学者ブラッド・コックスが開発した「[[Objective-C]]」はSmalltalkをモデルにしてそれを平易化した言語であった。そのメッセージレシーバーはメソッドリストにないセレクタを受け取った場合にのみ動的ディスパッチ機構に移るというスタイルで形式化された。メッセージレシーバの仕組みは[[遠隔手続き呼出し]]/[[Object Request Broker|オブジェクト要求ブローカー]]の実装に適していたので[[分散システム]]とオブジェクト指向の親和性を認識させることになった。
 
=== プロトタイプベースの考案(1985 - 90) ===
[[Smalltalk]]のオブジェクト指向は[[アラン・ケイ]]がその影響を言及していた[[LISP]]コミュニティを逆に感化して、Smalltalkが示したメタ万物をオブジェクトの概念を通て扱う{{仮リンク|メタオブジェクト指向とプロトコル|en|Metaobject|label=}}を[[LISP]]プログラミングの連携向けた構想が練られる融合させようになっとする潮流を生みだした。これはLISPの基礎情報要素であるアトムとシンボル型に倣う形で、の集合体となるオブジェクトを構築し、シンボル型であるメンバ変数名/メンバ関数名自体実行時にその都度評価(''eval'')して実行時の内容を導出し、実際の変数実体の参照/関数実体の呼出につなげるというアイディアが生まれた。これは実装面では単に構想から、フレームと呼ばれる動的配列データ構造体のスロットに変数ポインタ/関数ポインタを付け替えするという機構実装などにまとめられた。識別子(変数名と関数名)シンボル型がマッピングされスロット増設削減可能あり原型実例元クラスと継承クラスポインタスロットも加えられた。これらは機能名としては[[メタクラス]]と呼ばれた。これらのメタオブジェクト設計プロトコルを導入して1985年に[[MIT人工知能研究所]]の[[LISPマシン]]上で「Flavors」が実装された。LISPの視点から保有スロット識別子にマッピングされたシンボル型構成判別による[[動的型付け]]の[[ダックタイピング]]の概念盛り込まれ、またシンボル型マッピング構成をパーツ部品化して多重継承させるという[[ミックスイン]]という設計がの機能も考案され、また実行時の逐次スロット識別子保有判別に焦点を当てた[[ダックタイピング]]の概念も生まれた。1988年にFlavorsのデザイン言語機能を[[Common Lisp]]に融合させた「[[CLOS]]」が公開されたが、こちらは関数を中心にして[[抽象データ型]]から距離を置いたスタイルになった。FlavorsおよびCLOSデザインは発表と並行して[[パロアルト研究所]]にも回帰されでは、計算機科学者デビッド・アンガーがSmalltalkの方言として制作する「[[Self]]」を1987年に初回稼働して901990年に一般公開した。LISPコミュニティから逆輸入されてSelfに導入されたメタオブジェクト設計プロトコルは、後に[[プロトタイプベース]]またはインスタンスベースと呼ばれるパラダイムに発展する。同時にそれと、従来の[[クラス (コンピュータ)|クラス]]機構を中心にしたオブジェクト指向言語を区別するための[[クラスベース]]という言葉も生まれた。
 
=== コンポーネントとネットワーク(1989 - 97) ===
55行目:
 
== 代表的なオブジェクト指向言語 ==
オブジェクト指向言語は、[[抽象データ型]]の仕組み沿っ準拠した[[クラスベース]]、{{仮リンク|メタオブジェクトの仕組みに沿っプロトコル|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]]にクラスベースのオブジェクト指向を追加したもの。当初はモジュールのデータ隠蔽的なカプセル化、単一継承、仮想関数による多態性という基本的なものだった。静的型付け重視である。[[ニクラウス・ヴィルト|ヴィルト]]監修の[[アップル (企業)|アップル社]]による初回バージョンを土台にして様々な企業団体による派生版が公開されており、その特徴と機能追加も様々である。
70行目:
:[[C++]]の柔軟性と融通性とは正反対のオブジェクト指向言語。[[クラスベース]]で[[静的型付け]]重視である。[[契約プログラミング|契約による設計]]に基づく[[表明|アサーション]]の挿入でクラスの状態および演算用の引数と返り値を細かくチェックできる。[[例外処理]]も備えられている。クラスメンバ(フィーチャー)はデータ、アクセッサ、ミューテイタの三種限定で[[多重定義|オーバーロード]]はできない。カプセル化の可視性は自身に依存するクラス(クライアント)を定義する形で決められる。多重継承可能であり、クラス間の繋がりを[[仮想継承]]機能、各種[[オーバーライド]]指定子、名前衝突を解決するリネーミング機能などで綿密に設定できる。多態性は[[仮想関数|延期関数/手続き]](サブタイプ多相)と[[ジェネリックプログラミング|ジェネリシティ]](パラメトリック多相)である。[[ガーベジコレクション]]機能が初めて導入されたオブジェクト指向言語でもある。
;[[Self]] 1987年
:[[メッセージパッシング|メッセージング]]構文ベースのオブジェクト指向言語でSmalltalkの方言として開発されたデフォルそれ故にプロ配備のオブジェクタイプからプロタイプを派生させ、またインスタンスを複製してのスロット任意のプロパティとメソッドを[[ダイナミックバインディング|動的バインディング]]できるというメタオブジェクトプロトコルも忠実に実装された。[[プロトタイプベース]]を初めて導入したオブジェクト指向言語でもあというパラダイムはこのSelfから認知され。ゆえようなった。[[動的型付け]]重視である。当初はSmalltalkの派生言語として公開されており、それと同様に専用のランタイム環境上で実行され、GUI運用環境の構築も目標にしていた。Selfのランタイム環境は[[実行時コンパイラ]]機能を初めて実装したことで知られており画期的な処理速度を実現している。この技術は[[Java仮想マシン]]の土台になった。
;[[Common Lisp]]([[CLOS]]) 1988年(ANSI規格化は1994年)
:[[クラスベース]]のオブジェクト指向。メソッド記述の関数呼び出し形式への統合、[[多重ディスパッチ]]、クラスの動的な再定義等を特徴とする。
;[[Python]] 1994年
:[[プロトタイプベース]]のオブジェクト指向スクリプト言語。[[基本データ型]]や[[コンテナ (データ型)|コレクション型]]などよく使われるデータ要素を全て組み込みのオブジェクトにしており、いる。それらは[[手続き型プログラミング|手続き型]]スタイルでの関数の対象値として気軽にいやすく、またえる。コレクション型を扱うのに適した[[関数型プログラミング|関数型]]構文も導入されている。関数もオブジェクトなので柔軟に扱える。オブジェクトは自由にプロパティとメソッドを付け替えして様々に応用できるようデザインされている。オブジェクトは[[ダックタイピング]]で型判別されるので変数ないし関数の型宣言と型注釈は撤廃されている。ゆえに[[動的な型付け|動的型付け]]重視である。Pythonのプロトタイプオブジェクトはクラスと呼ばれている。多重継承可能であり親要素の参照順序はC3線形化で解決されている。アクセスコントロールはなくデータ抽象を軽視するコードスタイルと相まってカプセル化は備えられていない。多態性はメソッドの動的バインディングで行われる。後期バージョンで型ヒントが追加され、それに伴い[[ジェネリクス]]も導入された。
;[[Java]] 1995年
:[[C++]]をモデルにしつつ堅牢性とセキュリティを重視した[[クラスベース]]のオブジェクト指向言語。静的型付け重視である。パッケージ中心のカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性と、基本に忠実なクラスベースである。C++風の[[ポインタ (プログラミング)|ポインタ]]と値型インスタンスは除外されて参照型インスタンスに統一した。[[例外処理]]を整備し[[演算子オーバーロード]]を除外した。オブジェクト指向と[[マルチスレッド]]の調和が図られ、[[ソフトウェアコンポーネント|コンポーネント指向]]による動的クラスローディングの存在感が高められている。クラスメタデータを操作できる[[リフレクション (情報工学)|リフレクション]]は初期から採用された。中期から[[ジェネリクス]](パラメトリック多相)と[[アノテーション|メタアノテーション]](アドホック多相)が導入され、ラムダ式と関数型インターフェースを軸にした[[関数型言語|関数型構文]]も採用された。[[仮想マシン]]上で実行される。[[仮想マシン]]と[[ガーベジコレクション]]の技術は比較的高度と見なされている。
86行目:
:[[Java]]を強く意識してマイクロソフト社が開発したクラスベースのオブジェクト指向言語。Javaよりも[[マルチパラダイムプログラミング言語|マルチパラダイム]]の性質が強化されており、言語仕様も比較的大規模と言える。ステートメント書式と各種データ型の取り扱いに、C++風の柔軟性と融通的を残しながら様々な[[糖衣構文]]サポートも加えてコーディング上の利便性がより高められている。[[マルチスレッド]]仕様も整備されている。アドホック多相では拡張メソッド、インデクサ、演算子オーバーロードなどを備えている。パラメトリック多相では[[共変性と反変性 (計算機科学)|共変/反変]]も扱える[[ジェネリクス]]を備えている。サブタイプ多相はクラスは単一継承でインターフェースは多重実装と基本通りである。[[関数型言語|関数型構文]]も整備されており、特にメソッド参照機能であるデリゲートの有用性が高められている。デリゲートは[[イベント駆動型プログラミング|イベント駆動構文]]の平易な表現も可能にしている。基本は[[静的型付け]]であるが、動的束縛型と[[ダックタイピング]]による[[動的型付け]]の存在感が高められているので漸進的型付けの言語と見なされている。[[.NET Framework]]([[共通言語基盤]]=仮想実行システム)上で実行される。
;[[Scala]] 2003年
:[[クラスベース]]のオブジェクト指向と[[関数型プログラミング]]を融合させた言語。[[クラス (コンピュータ)|クラス]]機構と関数型の[[型システム]]に同等の比重が置かれており静的型付け重視である。[[ミックスイン]]相当の[[トレイト]]と、[[共変性と反変性 (計算機科学)|共変/反変]]および抽象タイプメンバを扱える[[ジェネリクス]]を連携させた多態性が重視されておりオブジェクトを様々に[[派生型|派生型付け]]できる。シングルトンオブジェクトの役割が形式化されて従来のクラス静的メンバの新解釈にも用いられている。専用の定義書式により[[イミュータブル]]なオブジェクトが重視されている。上述の派生型付けスタイルとオブジェクト引数の[[逆写像|抽出]]構文および[[パターンマッチング|パターンマッチング式]]の併用連鎖計算は[[モナド (プログラミング)|モナド]]を彷彿とさせるものであり、[[抽象データ型]]を値とし扱う独特の関数型スタイルを表現できる。[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。
;[[Kotlin]] 2011年
:静的型付けの[[クラスベース]]のオブジェクト指向であるが、[[手続き型プログラミング]]に回帰しており、クラス枠外の関数とグローバル変数の存在感が高められている。クラスはpublicアクセスとfinal継承がデフォルトにされて、カプセル化と継承が公然と軽視されている。これによりインスタンスは手続き型の関数の対象値としての役割が強められ、その操作をサポートする関数型構文も導入されている。仮想関数と抽象クラスによる多態性は標準通りである。[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。
96行目:
== 用語と解説 ==
;[[クラス (コンピュータ)|クラス]]
:クラス(''class'')の仕組みを中心にしたオブジェクト指向を[[クラスベース]]と言う。クラスはデータメンバとメソッドをまとめたものであり、[[プログラム意味論|操作的意味論]]を付加された静的[[構造体|レコード]]とも解釈される。クラスはインスタンスのひな型になであり、インスタンスはクラスを実例化(量化)したものである。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化はデータメンバとメソッドの可視性を指定する機能である。継承は自身のスーパークラスを指定する機能である。多態性はオーバーライドと[[仮想関数テーブル]]を処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。
;プロトタイプオブジェクト
:プロトタイプ(''prototype'')の仕組みを中心にしたオブジェクト指向を[[プロトタイプベース]]と言う。プロトタイプベースで言われるオブジェクトとは識別名&中間参照ポインタペア動的配列集合体を指す。この動的配列集合体は一般にフレームと呼ばれる。識別名&中間参照ポインタペアの割り当て箇所は一般にスロットと呼ばれる。スロットにはデータメンバとメソッドの識別名&中間参照ペアが代入されるので、オブジェクプロタイプはクラスと同様にデータメンバとメソッドをまとめたものになる。プロトタイプベースの実装形式は言語ごと様々であるが、基本はおおむね次のうになる。オブジェクトはプロトタイプオブジェクトとクローンオブジェクトに分かれる。前者ってはクラス、後者はインスタンスに当たるものである。前者はシステム提供プロトタイプユーザー定義プロトタイプに分か呼ばている。プログラマはシステム提供する基底プロトタイプに、自由にデータメンバとメソッド付け足して任意の派生させてユーザー定義プロトタイプを作成できる。プロトタイプは規定また「型」相当であり、それを複製する方式で生成されるインスタンス事前の設計に基づいた「値」相当である。データメンバとメソッドはその参照にインスタンス保持必要とするものと、ておりないものに分かれる。前者はインスタンスメンバクロー後者は静的メオブジェクトのひな型相当するものである。クロインスタンスにも自由にデタメバとメソッドを付け足すことができる。インスタンスはそのプロトタイプへの参照を保持しており、プロトタイプはその親プロトタイプへの参照を保持している。これは継承相当の機能になっている。プロトタプを複製してクローオブジェクトが生成される。クロースタオブジェクトはそスへプロトタイプと同じデータメンバとメソッドを保持する事に自由るが、プロトタイプ専用に指定されたメンバは除かれる。クローンオブジェクトのメソッドは自由に付け替えできるので、これは多態性相当の機能になっている。ただしプロトタイプは動的な関数型言語由来の仕様なので、クラスを用いるOOPの三大要素とはまた違った視点から眺める必要がある。
;[[メッセージ (コンピュータ)|メッセージ]]
:オブジェクト指向で言われるメッセージ(''message'')は、複数方面の考え方が混同されている曖昧な用語になっている。元々はSmalltalkから始まったメッセージ構文ングベースのオブジェクト指向の中心機構メカニズムである。以前はクラスベースの方でもメソッドの呼び出しをメッセージを送るという具合に考えることが推奨されていた。メッセージはオブジェクトのコミュニケーション手段と標榜されているが、その忠実な実装内容はそれほど知られていないのが実情である。最も混同されているものに[[アクターモデル]]があるが、そこで言われる非同期性とオブジェクト指向で言われる遅延性は現行の実装スタイルではそれほど共通していない。[[リモートプロシージャコール]]と[[Object Request Broker|オブジェクトリクエストブローカー]]の働き方もメッセージパッシングと呼ばれることが多いが、その仕様と機能は動的ディスパッチに該当するものである。メッセージのオブジェクト指向的運用はメッセージングと名付けられているが、普通にメッセージパッシングとも呼ばれている。具体的な機能例としてはSmalltalk、Objective-C、Selfの[[メッセージ転送|メッセージレシーバー]]と、Rubyのメソッドミッシングなどがある。ただしこれらは[[アラン・ケイ]]のメッセージング構想の本質を得ているもの忠実な再現にまでは到っていない。
;[[インスタンス]]
:(''instance'')はクラスベースではクラスを実化(量化)したものであり、実装レベルで言うとデータメンバと仮想関数テーブルをメモリ上に展開したものになる。プロトタイプベースではプロトタイプオブジェクトのクローンを複製する方式で生成されたオブジェクトを指す。実装レベルで言うとメモリ上に展開された識別名&中間参照ポインタペアの動的配列になる。
;[[フィールド (計算機科学)|データメンバ]]
:(''data member'')はクラスまたはオブジェクトに属する変数。言語によってフィールド、プロパティ、メンバ変数、属性と呼ばれる。データメンバは、クラスデータメンバとインスタンスデータメンバに分かれる。クラスデータメンバは静的データメンバとも呼ばれる。その中で定数化されたものはクラス[[定数 (プログラミング)|定数]]と呼ばれる。クラスデータメンバはクラス名の名前空間でスコープされたグローバル変数と同じものであり、プログラム開始時から終了時まで確保される。インスタンスデータメンバはインスタンス生成時にメモリ上に確保されるものであり、その破棄時に消滅する。インスタンスデータメンバの参照にはそのthis参照が必要である。プロトタイプベースではプロトタイプオブジェクト専用ので定義されたデータメンバでそのアクセスにインスタンス(self)を必要としないものが静的データメンバ相当になる。
;[[メソッド (計算機科学)|メソッド]]
:(''method'')はクラスまたはオブジェクトに属する関数。言語によってはメンバ関数とも呼ばれる。データメンバの参照に特化したものはゲッター(''getter'')アクセッサ(''accessor'')と呼ばれる。データメンバの変更に特化したものはセッター(''setter'')ミューテイタ(''mutator'')と呼ばれる。メソッドは、クラスメソッドとインスタンスメソッドに分かれる。クラスメソッドは静的メソッドとも呼ばれる。クラスメソッドはクラス名の名前空間でスコープされたグローバル関数と同じものである。インスタンスメソッドを呼び出すにはそのインスタンスthis参照が必要になり、これはthis参照と呼ばれである。プロトタイプベースではプロトタイプオブジェクト専用ので定義されたメソッドでそのアクセスにインスタンス(self)を必要としないものが静的メソッド相当になる。
;[[コンストラクタ]]
:(''constructor'')はインスタンス生成時に呼び出されるそのクラスのメソッドである。インスタンスデータメンバを任意の値で初期化するためのものであるが、その他の初期化コードも記述できる。プロトタイプベースではシステム提供プロトタイプが保持する生成用メソッドまたは生成用のグローバル関数がコンストラクタ相当になる。
147行目:
 
;[[メタクラス]]
:(''metaclass''){{仮リンラス自体の定義情報|メタオブジェクトプロトコル|en|Metaobject|label=}}に準拠した機能名であり、その実装方式は言語毎に違いがある。メタクラスが持つとされるは、クラスのデータメンバ、メソッド、スーパークラス、内部クラスなどの定義情報を記録されいわゆる[[メタデータ]]である。メタクラスのインスタンス(実例化)がクラスになる。クラスベースのメタクラス機能は、実装レベルではシステム側が用意している特別なシングルトンオブジェクトと考えた方が分かりやすい。それにはほとんどの場合システム側が提供する抽象インターフェースを通してのみアクセスできる。メタクラスの各種定義情報を参照またはないし変更できる機能はリフレクションと呼ばれる。メタクラスの変更はその対象実例クラスに直ちに反映される。プロトタイプベースのメタクラスベー機能では、メタクラもプログラマが自由に扱えるオブジェクトになるの用いられ、メタクラスのそのまたメタクラスを定義でき[[形而上学|形而上]]関係存在し、基底メタクラスと派生メタクラスを定義きる[[継承 (プログラミング)|継承]]関係も存在する。またメタクラス/クラスの実体を指す「eigenclass」といったプログラム概念も存在する。
;[[リフレクション (情報工学)|リフレクション]]
:(''reflection'')は、メタクラスの定義情報内容を参照または変更する機能であるが、言語ごとに変更できる定義情報内容の範囲は異なっている。データメンバではデータ型、識別子、可視性が変更対象になる。メソッドではリターン型、識別子、パラメータリスト、可視性、仮想指定が変更対象になる。双方の追加定義と削除もできる事がある。スーパークラスも変更できる事がある。また、実行時の文字列(char配列やString)をデータメンバとメソッドの内部識別子として解釈できる機能もリフレクションに当たる。これは実行時の文字列によるデータメンバの参照とメソッドの呼び出しを可能にする。
;[[アノテーション|メタアノテーション]]
:(''metadata annotation'')はクラスに任意の情報を埋め込める機能である。情報とは文字列と数値からなるキーワード、シンボル、テキストである。プログラマが自由な形式で書き込んで随時読み取るものであるが、システムから認識される形式のものもある。実装レベルではメタクラスに書き込まれてリフレクション機能またはその[[糖衣構文]]で読み取ることになる。[[マーカーインタフェース|マーカーインターフェース]]の拡張とも見なされている。メタアノテーションはクラス単位だけでなく、言語によってはインスタンス単位やメソッド単位でも埋め込むことができる。アドホック多相とされる。
168行目:
:(''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'')は、基準クラス及びその基底型の値が代入、束縛、適用されるという宣言になる。