コンテンツにスキップ

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

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

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
Baudanbau20 (会話) による ID:78849842 の版を取り消し 編集衝突感があるので取り消しておき
タグ: 取り消し
20行目: 20行目:


=== カプセル化 ===
=== カプセル化 ===
一定の関連性を持つデータ(変数、プロパティ)と、それらを操作するコー(関数、プロシージャ)をひとまとめにしてオブジェクトとし、外部に対して必要とされるデータとコードのみを公開し、それ以外を内部に隠蔽する仕組みがカプセル化と呼ばれる。オブジェクトが持つコードは一般にメソッドと呼ばれる。オブジェクトの設計は{{仮リンク|単一責任の原則|en|Single-responsibility principle|label=}}に準拠して一つの閉じた機能を構成するデータ群とそれに関連したメソッド群を定義するのが基本になる。公開されたデータは外部のメソッドから直接参照ないし変更する事できる。公開されたメソッドは外部のメソッドから直接呼び出す事ができる。隠蔽されたデータとメソッドは外部からアクセスできず、これは{{仮リンク|情報隠蔽|en|information hiding}}と呼ばれる。
一定の関連性を持つデータ(変数、プロパティ、フィールド)と、それらを操作するメソッドをひとまとめにしてオブジェクトとし、外部に対して必要とされるデータとメソッドのみを公開し、それ以外を内部に隠蔽する仕組みがカプセル化と呼ばれる。公開されたデータは外部のメソッドから直接参照ないし変更する事できる。公開されたメソッドは外部のメソッドから直接呼び出す事ができる。隠蔽されたデータとメソッドは外部からアクセスできず、これは{{仮リンク|情報隠蔽|en|information hiding}}と呼ばれる。メソッドを通してデータを参照ないし変更する仕組みはデータの抽象化を表現する。データを参照するメソッドはゲッターまたはアクセッサ、データを変更するメソッドはセッターまたはミューテイタと呼ばれる。


=== 継承 ===
=== 継承 ===
既存オブジェクトのデータ構成とメソッド構成を引き継いで、新しい派生オブジェクトを定義する仕組みが継承と呼ばれる。引き継ぐ際には新たなデータとメソッドを自由に追加できるので、派生オブジェクトの構成は既存内容+追加内容になる。既存オブジェクトは親オブジェクト、派生オブジェクトは子オブジェクトと呼ばれる。クラスベースのOOPでは、親をスーパークラス、子をサブクラスと呼ぶ。親オブジェクトの適用箇所は子オブジェクトで置き換えても結果が同一になることが求められており、これは[[リスコフの置換原則]]と呼ばれる。一つのスーパークラスを継承するのは単一継承と呼ばれる。複数個のスーパークラスを継承してそれぞれの構成内容を引き継ぐのは多重継承と呼ばれる。抽象化に注目した継承の方は{{仮リンク|インターフェース分離の原則|en|Interface segregation principle|label=}}に準じたものになり、[[統一モデリング言語|UML]]では実現と呼ばれるものになる。これは一定のオブジェクトに共通した振る舞い局面を抜き出して抽象化する仕組みを指し、その抽象化オブジェクトは[[インタフェース (抽象型)|インターフェース]]、[[トレイト]]、プロトコルなどと呼ばれる。
既存オブジェクトのデータ構成とメソッド構成を引き継いで、新しい派生オブジェクトを定義する仕組みが継承と呼ばれる。引き継ぐ際には新たなデータとメソッドを自由に追加できるので、派生オブジェクトの構成は既存内容+追加内容になる。既存オブジェクトは親オブジェクト、派生オブジェクトは子オブジェクトと呼ばれる。クラスベースでは、親をスーパークラス、子をサブクラスと呼ぶ。一つのスーパークラスを継承するのは単一継承と呼ばれる。複数個のスーパークラスを継承してそれぞれの構成内容を引き継ぐのは多重継承と呼ばれる。抽象化に注目した継承の方は、[[統一モデリング言語|UML]]では実現と呼ばれるものになる。これは一定のオブジェクトに共通した振る舞い局面を抜き出して抽象化する仕組みを指し、その抽象化オブジェクトは[[インタフェース (抽象型)|インターフェース]]、[[トレイト]]、プロトコルなどと呼ばれる。


=== 多態性 ===
=== 多態性 ===
異なる種類のオブジェクトに同一の操作インターフェースを持たせる仕組みが多態性と呼ばれる。オブジェクト指向視点の多態性は、クラスの派生関係またはオブジェクトの動的バインディングによって、コンパイル時のメソッド名から呼び出されるプロセス内容実行時に決定されるという機構を意味する{{仮リンク|サブタイプ多相|en|subtyping|label=}}を指す。サブタイプ多相は{{仮リンク|仮想関数(OOP)|en|Virtual function|label=仮想関数}}、[[多重ディスパッチ]]、{{仮リンク|動的ディスパッチ|en|Dynamic dispatch|label=}}の三手法に分類される。最もよく知られる仮想関数は多態性と同義に説明される事が多い。'''仮想関数'''は、メソッドが所属するクラスの派生関係のみに焦点を当てたシングルディスパッチであり、スーパークラス[[関数プロトタイプ|抽象メソッド]]への呼び出しから、その実行時のサブクラス実装メソッドに多方向分岐させるプロセスを指す。その際は[[関数へのポインタ|各メソッドへのポインタ]]を連ねた[[Vtable|仮想呼出テーブル]]と呼ばれる仕組みが用いられる。抽象メソッドの使用は[[依存性逆転の原則]]に準じたものである。抽象メソッドの定義を連結点にした具体メソッドの実装は[[開放/閉鎖原則|開放閉鎖の原則]]に準じたものであり、閉鎖=抽象は設計の不変性、開放=具体は実装の拡張性を表わす。'''多重ディスパッチ'''は、メソッドが所属するクラスの派生関係に加えて、メソッドの各引数のクラスの派生関係にも注目した形態である。各引数は実行時に[[ダウンキャスト|型ダウンキャスト]]されて、それらの引数型の組み合わせに対応したプロセスに分岐する。メソッド所属クラスの派生関係が絡まない場合は単一引数だとシングルディスパッチになる。多重ディスパッチの中でもプロセス分岐に関与するクラスが二つに限定されたものは[[ダブルディスパッチ]]と個別定義されている。サブタイプ多相における'''動的ディスパッチ'''は、[[プロトタイプベース]]のオブジェクトのメソッド名スロットに差し込まれる実体メソッド参照が随時切り替えられることで、そのメソッド名から呼び出されるプロセス実行時に決定されるという仕組みを指す。[[クラスベース]]の方では[[リフレクション (情報工学)|リフレクション]]機能によって同様に、メソッド名から呼び出されるプロセス内容が実行時に決まるという仕組みが実装される。
異なる種類のオブジェクトに同一の操作インターフェースを持たせる仕組みが多態性と呼ばれる。オブジェクト指向視点の多態性は、クラスの派生関係またはオブジェクトの動的バインディングによって、コンパイル時のメソッド名から呼び出されるプロセス内容実行時に決定されるという機構を意味する{{仮リンク|サブタイプ多相|en|subtyping|label=}}を指す。サブタイプ多相は{{仮リンク|仮想関数(OOP)|en|Virtual function|label=仮想関数}}、[[多重ディスパッチ]]、{{仮リンク|動的ディスパッチ|en|Dynamic dispatch|label=}}の三手法に分類される。最もよく知られる仮想関数は多態性と同義に説明される事が多い。'''仮想関数'''は、メソッドが所属するクラスの派生関係のみに焦点を当てたシングルディスパッチであり、スーパークラス抽象メソッドへの呼び出しから、それを[[オーバーライド]]したサブクラス実装メソッドに分岐させる機能を指す。その際は[[関数へのポインタ|各メソッドへのポインタ]]を連ねた[[Vtable|仮想呼出テーブル]]と呼ばれる仕組みが用いられる。'''多重ディスパッチ'''は、メソッドが所属するクラスの派生関係に加えて、メソッドの各引数のクラスの派生関係にも注目した形態である。各引数は実行時に[[ダウンキャスト|型ダウンキャスト]]されて、それらの引数型の組み合わせに対応したプロセスに分岐する。メソッド所属クラスの派生関係が絡まない場合は単一引数だとシングルディスパッチになる。多重ディスパッチの中でもプロセス分岐に関与するクラスが二つに限定されたものは[[ダブルディスパッチ]]と個別定義されている。サブタイプ多相における'''動的ディスパッチ'''は、[[プロトタイプベース]]のオブジェクトのメソッド名スロットに差し込まれる実体メソッド参照が随時切り替えられることで、そのメソッド名から呼び出されるプロセス実行時に決定されるという仕組みを指す。[[クラスベース]]の方では[[リフレクション (情報工学)|リフレクション]]機能によって同様に、メソッド名から呼び出されるプロセス内容が実行時に決まるという仕組みが実装される。


=== メッセージパッシング ===
=== メッセージパッシング ===
69行目: 69行目:
:[[メッセージパッシング]]のプログラム概念を導入した最初の言語。数値、真偽値、文字列から変数、コードブロック、メタデータまでのあらゆる要素をオブジェクトとするアイディアを編み出した最初の言語でもある。オブジェクト指向という言葉はSmalltalkの言語設計を説明する中で生み出された。オブジェクトにメッセージを送るという書式であらゆるプロセスを表現することが目標にされている。[[メッセージ転送|メッセージレシーバー]]と[[委譲]]の仕組みは、形式化されてない動的ディスパッチと[[ダイナミックバインディング|動的バインディング]]相当のものであり[[プロトタイプベース]]の源流になった。専用のランタイム環境上で動作させる設計は、実行時多態性とセキュリティにも繋がるモニタリングを実現した。これは後に[[仮想マシン]]や[[仮想実行システム]]と呼ばれるものになる。
:[[メッセージパッシング]]のプログラム概念を導入した最初の言語。数値、真偽値、文字列から変数、コードブロック、メタデータまでのあらゆる要素をオブジェクトとするアイディアを編み出した最初の言語でもある。オブジェクト指向という言葉はSmalltalkの言語設計を説明する中で生み出された。オブジェクトにメッセージを送るという書式であらゆるプロセスを表現することが目標にされている。[[メッセージ転送|メッセージレシーバー]]と[[委譲]]の仕組みは、形式化されてない動的ディスパッチと[[ダイナミックバインディング|動的バインディング]]相当のものであり[[プロトタイプベース]]の源流になった。専用のランタイム環境上で動作させる設計は、実行時多態性とセキュリティにも繋がるモニタリングを実現した。これは後に[[仮想マシン]]や[[仮想実行システム]]と呼ばれるものになる。
;[[C++]] 1983年
;[[C++]] 1983年
:[[C言語]]に[[クラスベース]]のオブジェクト指向を追加したもの。Simulaの影響を受けている。[[静的型付け]]の[[クラス (コンピュータ)|クラス]]が備えられて、カプセル化、継承、多態性の三仕様を実装している。カプセル化はフレンド指定で寛容化されている。継承は多重可能であり継承の可視性も指定できる。多態性は[[仮想関数]]によるサブタイプ多相、[[テンプレート (プログラミング)|テンプレートクラス&関数]]によるパラメトリック多相、[[多重定義|関数&演算子オーバーロード]]によるアドホック多相が導入されている。元がC言語であるため、オブジェクト指向から逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。
:[[C言語]]に[[クラスベース]]のオブジェクト指向を追加したもの。Simulaの影響を受けている。[[静的型付け]]の[[クラス (コンピュータ)|クラス]]が備えられて、カプセル化、継承、多態性の三仕様を実装している。カプセル化はフレンド指定で寛容化されている。継承は多重継承可能であり継承の可視性も存在し[[菱形継承問題]]解決用の[[仮想継承]]も導入されている。多態性は[[仮想関数]]によるサブタイプ多相、[[テンプレート (プログラミング)|テンプレートクラス&関数]]によるパラメトリック多相、[[多重定義|関数&演算子オーバーロード]]によるアドホック多相が導入されている。元がC言語であるため、オブジェクト指向から逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。
;[[Objective-C]] 1984年
;[[Objective-C]] 1984年
:[[C言語]]に[[メッセージパッシング|メッセージ]]構文ベースのオブジェクト指向を追加したもの。こちらはSmalltalkの影響を受けており、それに準じた[[メッセージパッシング]]の書式が備えられた。メッセージを受け取るクラスの定義による[[静的型付け]]と共に、メッセージを[[委譲]]するオブジェクトの実行時決定による[[動的型付け]]も設けられている。オブジェクト指向的にはC++よりも正統と見なされた。[[制御構造|制御構造文]]が追加され、メッセージを送る書式も平易化されており、Smalltalkよりも扱いやすくなった。
:[[C言語]]に[[メッセージパッシング|メッセージ]]構文ベースのオブジェクト指向を追加したもの。こちらはSmalltalkの影響を受けており、それに準じた[[メッセージパッシング]]の書式が備えられた。メッセージを受け取るクラスの定義による[[静的型付け]]と共に、メッセージを[[委譲]]するオブジェクトの実行時決定による[[動的型付け]]も設けられている。オブジェクト指向的にはC++よりも正統と見なされた。[[制御構造|制御構造文]]が追加され、メッセージを送る書式も平易化されており、Smalltalkよりも扱いやすくなった。
75行目: 75行目:
:[[Pascal]]にクラスベースのオブジェクト指向を追加したもの。厳格なカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性といった基本に忠実な静的型付け重視である。[[多重定義|関数&演算子オーバーロード]](アドホック多相)と[[ジェネリックプログラミング|ジェネリクス]](パラメトリック多相)は除外された。
:[[Pascal]]にクラスベースのオブジェクト指向を追加したもの。厳格なカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性といった基本に忠実な静的型付け重視である。[[多重定義|関数&演算子オーバーロード]](アドホック多相)と[[ジェネリックプログラミング|ジェネリクス]](パラメトリック多相)は除外された。
;[[Eiffel]] 1986年
;[[Eiffel]] 1986年
:[[Pascal]]にクラスベースのオブジェクト指向を追加した[[静的型付け]]重視の言語。[[契約プログラミング]]を理念にしている。[[多重定義]]抑制方針を強調しており、[[多重定義|関数&演算子オーバーロード]]は除外されたが、[[ジェネリックログラミング|ジェネリッククラス]]は相反しないものして導入されている。多重継承を採用しているが、継承間で名前衝突する全メンバはオーバーライドとリネーミングによる事前解決が求められリネーミングは名前衝突するメンバを任意の名義で単一化する機能でる。Eiffelではメンバ名の重複を無くすことで[[菱形継承問題]]を解決している。[[ガーベジコレクション]]機能が初めて導入されたオブジェクト指向言語でもある。
:[[C++]]の柔軟性と融通性とは正反対のオブジェクト指向言語。[[クラスベース]]で[[静的型付け]]重視である。[[契約プログラミング]]を理念にしており、アサーションの挿入でクラスの状態とメソッド引数&返り値を細かくチェックできる。クラスメンバ(フィーチャー)は属性、アクセッサ、ミューテイタの三種限定で[[多重定義|オーバーロード]]はできない。カセル化の可視性は自身に依存するクラス(クライアント)を定義するという形で決められる。多重継承可能でありクラス間の繋がりを[[仮想継承]]機能、各種[[オーバーライド]]指定子、名衝突を解決るリネーミング機能など綿密に設定できる。仮想関数、[[ジェネリックプログラミング|ジェネリッククラス]]も導入されている。[[ガーベジコレクション]]機能が初めて導入されたオブジェクト指向言語でもある。
;[[Self]] 1987年
;[[Self]] 1987年
:[[メッセージパッシング|メッセージ]]構文ベースのオブジェクト指向言語。標準配備のオブジェクトを複製して、そのスロットに任意のプロパティとメソッドを[[ダイナミックバインディング|動的バインディング]]できるという[[プロトタイプベース]]を初めて導入したオブジェクト指向言語でもある。ゆえに[[動的型付け]]重視である。Smalltalkと同様に専用のランタイム環境で実行されたが、これも実用面では初となる[[実行時コンパイラ]](''just-in-time compiler'')機能が備えられて速度面でも画期的なものになった。
:[[メッセージパッシング|メッセージ]]構文ベースのオブジェクト指向言語。標準配備のオブジェクトを複製して、そのスロットに任意のプロパティとメソッドを[[ダイナミックバインディング|動的バインディング]]できるという[[プロトタイプベース]]を初めて導入したオブジェクト指向言語でもある。ゆえに[[動的型付け]]重視である。Smalltalkと同様に専用のランタイム環境で実行されたが、これも実用面では初となる[[実行時コンパイラ]](''just-in-time compiler'')機能が備えられて速度面でも画期的なものになった。
81行目: 81行目:
:[[Common Lisp]]に[[プロトタイプベース]]に似たオブジェクト指向を追加したもの。データオブジェクトとメソッドオブジェクトに分離されており、前者のスロットには任意の変数を、後者のスロットには任意の関数を[[ダイナミックバインディング|動的バインディング]]できる動的型付け重視である。動的型付けのデータオブジェクトを引数にしたメソッドによる[[多重ディスパッチ]]が重視されている。
:[[Common Lisp]]に[[プロトタイプベース]]に似たオブジェクト指向を追加したもの。データオブジェクトとメソッドオブジェクトに分離されており、前者のスロットには任意の変数を、後者のスロットには任意の関数を[[ダイナミックバインディング|動的バインディング]]できる動的型付け重視である。動的型付けのデータオブジェクトを引数にしたメソッドによる[[多重ディスパッチ]]が重視されている。
;[[Python]] 1994年
;[[Python]] 1994年
:[[プロトタイプベース]]と[[クラスベース]]の双方を兼ねたオブジェクト指向スクリプト言語。静的型付けのクラスと動的型付けのインスタンスが併用されているが、後者の動的バインディングの比重が大きめである。[[ダックタイピング]]を重視する方針により型宣言制約が撤廃されている。多態性は動的ディスパッチを中心にし、メソッドシグネチャと[[関数プロトタイプ]]を操作できる[[リフレクション (情報工学)|リフレクション]]によって更に柔軟性が図られている。これらにより動的型付け重視である。ジェネリッククラスとジェネリック関数も導入されており、動的な柔軟性と静的な多様性の双方を使い分けられる。言語仕様を比較的簡素化し、[[インタプリタ]]式動作なので堅牢性も高い。
:[[プロトタイプベース]]と[[クラスベース]]の双方を兼ねたオブジェクト指向スクリプト言語。静的型付けのクラスと動的型付けのインスタンスが併用されているが、後者の動的バインディングの比重が大きめである。[[ダックタイピング]]を重視する方針により型宣言制約が撤廃されている。多態性は動的ディスパッチを中心にし、メソッドシグネチャと[[関数プロトタイプ]]を操作できる[[リフレクション (情報工学)|リフレクション]]によって更に柔軟性が図られている。これらにより動的型付け重視である。ジェネリッククラスとジェネリック関数も導入されており、動的な柔軟性と静的な多様性の双方を使い分けられる。構文と書式を比較的簡素化し、[[インタプリタ]]式動作なので堅牢性も高い。
;[[Java]] 1995年
;[[Java]] 1995年
:[[C++]]をモデルにしつつ堅牢性とセキュリティを重視した[[クラスベース]]のオブジェクト指向言語。静的型付け重視である。パッケージ中心のカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性と、基本に忠実なクラスベースである。[[多重定義|メソッドオーバーロード]]と、クラスメタデータを操作できる[[リフレクション (情報工学)|リフレクション]]は初期から採用された。データコンテナ系のクラスと関数型インターフェースなどに限ってジェネリッククラスが導入されている。C++の[[ポインタ (プログラミング)|ポインタ]]と値型インスタンスと[[演算子オーバーロード]]は真っ先に除外され、[[例外処理]]は残された。[[仮想マシン]]上で実行される。[[仮想マシン]]と[[ガーベジコレクション]]の技術は比較的高度と見なされている。
:[[C++]]をモデルにしつつ堅牢性とセキュリティを重視した[[クラスベース]]のオブジェクト指向言語。静的型付け重視である。パッケージ中心のカプセル化、単一のみの継承、仮想関数と多重実装可な[[インタフェース (抽象型)|インターフェース]]による多態性と、基本に忠実なクラスベースである。[[多重定義|メソッドオーバーロード]]と、クラスメタデータを操作できる[[リフレクション (情報工学)|リフレクション]]は初期から採用された。データコンテナ系のクラスと関数型インターフェースなどに限ってジェネリッククラスが導入されている。C++の[[ポインタ (プログラミング)|ポインタ]]と値型インスタンスと[[演算子オーバーロード]]は真っ先に除外され、[[例外処理]]は残された。[[仮想マシン]]上で実行される。[[仮想マシン]]と[[ガーベジコレクション]]の技術は比較的高度と見なされている。
87行目: 87行目:
:[[Object Pascal]]を発展させたもの。それと同様にこちらも基本に忠実なクラスベースで静的型付け重視であった。当初はデータベース操作プログラム開発を主な用途にして公開された。クラスとレコード([[構造体]])に同等の比重が置かれていた。一時期Javaの対抗馬になった。
:[[Object Pascal]]を発展させたもの。それと同様にこちらも基本に忠実なクラスベースで静的型付け重視であった。当初はデータベース操作プログラム開発を主な用途にして公開された。クラスとレコード([[構造体]])に同等の比重が置かれていた。一時期Javaの対抗馬になった。
;[[Ruby]] 1995年
;[[Ruby]] 1995年
:[[Python]]を意識して開発されたオブジェクト指向スクリプト言語。日本で誕生してグローバル化したプログラミング言語である。[[Smalltalk]]のオブジェクト指向を一つ理想にして動的型付け重視しいる。様々なパラダイム、様々な言語から有用なプログラミング手法を集めた技のデパートのような言語である。
:[[Python]]を意識して開発されたオブジェクト指向スクリプト言語。[[Smalltalk]]を一つの理想にして動的型付けを重視している。日本で誕生してグローバル化したプログラミング言語である。[[LISP]]とSmalltalkのメタプログラミング的なオブジェクト指向から、Pythonと[[JavaScript]]のプロトタイプベースなオブジェクト指向までスタイル幅広く取り入れおり、様々な有用なプログラミング手法を採用している技のデパートのような言語である。構文と書式は平易性を旨としている。
;[[JavaScript]] 1996年
;[[JavaScript]] 1996年
:[[Smalltalk]]の思想を受け継いでデザインされたオブジェクト指向スクリプト言語。当初は[[ウェブアプリケーション|WEBアプリケーション]]開発を主な用途にして公開された。[[プロトタイプベース]]であり、オブジェクトを純然たるスロットの集合体として定義している。スロットにはプロパティとメソッドが[[ダイナミックバインディング|動的バインディング]]され、[[ダックタイピング]]で型識別される。この仕組みによる[[動的な型付け|動的型付け]]が本命にされて、[[プリミティブ型]]以外の[[静的型付け]]が放棄されている。オブジェクトはプロトタイプのクローンであり、そのプロトタイプで分類される。プロトタイプの方は継承で体系化されている。[[ECMAScript]]として標準化されている。2015年版からは[[クラスベース]]向けの構文もサポートするようになった。
:[[Smalltalk]]の思想を受け継いでデザインされたオブジェクト指向スクリプト言語。当初は[[ウェブアプリケーション|WEBアプリケーション]]開発を主な用途にして公開された。[[プロトタイプベース]]であり、オブジェクトを純然たるスロットの集合体として定義している。スロットにはプロパティとメソッドが[[ダイナミックバインディング|動的バインディング]]され、[[ダックタイピング]]で型識別される。この仕組みによる[[動的な型付け|動的型付け]]が本命にされて、[[プリミティブ型]]以外の[[静的型付け]]が放棄されている。オブジェクトはプロトタイプのクローンであり、そのプロトタイプで分類される。プロトタイプの方は継承で体系化されている。[[ECMAScript]]として標準化されている。2015年版からは[[クラスベース]]向けの構文もサポートするようになった。
93行目: 93行目:
:[[Java]]を強く意識してマイクロソフト社が開発したクラスベースのオブジェクト指向言語。C++のクラスの性質を残しながらマルチパラダイムに発展させている。拡張メソッドや演算子オーバーロードなどのアドホック多相的なコーディングサポートが豊富である。パラメトリック多相は型変数の[[共変性と反変性 (計算機科学)|共変性と反変性]]、型引数への型制約指定を備えている。サブタイプ多相は、クラスは単一継承でインターフェースは多重実装と基本通りである。数々の[[関数型言語|関数型プログラミング]]機能も導入されている。基本は[[静的型付け]]であるが、動的束縛型(dynamic型)と[[ダックタイピング]]による[[動的型付け]]の存在感が高められているので、漸進的型付けの言語と見なされている。[[.NET Framework]]([[共通言語基盤]]=仮想実行システム)上で実行される。
:[[Java]]を強く意識してマイクロソフト社が開発したクラスベースのオブジェクト指向言語。C++のクラスの性質を残しながらマルチパラダイムに発展させている。拡張メソッドや演算子オーバーロードなどのアドホック多相的なコーディングサポートが豊富である。パラメトリック多相は型変数の[[共変性と反変性 (計算機科学)|共変性と反変性]]、型引数への型制約指定を備えている。サブタイプ多相は、クラスは単一継承でインターフェースは多重実装と基本通りである。数々の[[関数型言語|関数型プログラミング]]機能も導入されている。基本は[[静的型付け]]であるが、動的束縛型(dynamic型)と[[ダックタイピング]]による[[動的型付け]]の存在感が高められているので、漸進的型付けの言語と見なされている。[[.NET Framework]]([[共通言語基盤]]=仮想実行システム)上で実行される。
;[[Scala]] 2003年
;[[Scala]] 2003年
:[[クラスベース]]のオブジェクト指向と[[関数型プログラミング]]を融合させた言語。[[抽象データ型]]と、関数型の[[型システム]]に同等の比重が置かれており静的型付け重視である。パラメトリック多相とサブタイプ多相を連携させたバリアンスによる多態性が重視されている。型変数の継承関係による[[共変性と反変性 (計算機科学)|共変性と反変性]]で結ばれた[[トレイト]]の実装によ[[派生型|派生型付け]]されたオブジェクトは立体的に体系化される。トレイトは多重実装できる。型引数はアドホック多相に該当する型境界で制約されて静的な型チェックをサポートする。[[ジェネリクス]]と[[ミックスイン]]に分類されるトレイトの共存は[[ダックタイピング]]による型識別で実現されている。[[イミュータブル]]なオブジェクト生成と、オブジェクトの[[パターンマッチング]]式の導入も特徴である。
:[[クラスベース]]のオブジェクト指向と[[関数型プログラミング]]を融合させた言語。[[抽象データ型]]と、関数型の[[型システム]]に同等の比重が置かれており静的型付け重視である。パラメトリック多相とサブタイプ多相を連携させたバリアンスによる多態性が重視されている。型変数の継承関係による[[共変性と反変性 (計算機科学)|共変性と反変性]]で結ばれた、[[ミックスイン]]に分類される[[トレイト]]の実装によって[[派生型|派生型付け]]されたオブジェクトは立体的に体系化される。型引数はアドホック多相に該当する型境界で制約されて静的な型チェックをサポートする。[[イミュータブル]]なオブジェクト生成と、オブジェクトの[[パターンマッチング]]式の導入も特徴である。
;[[Kotlin]] 2011年
;[[Kotlin]] 2011年
:[[Javaバイトコード]]を出力し、[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。グローバル関数、グローバル変数の使用も容認されており、オブジェクト指向プログラミングを手続き型プログラミングのスタイルに崩したかのようにデザインされている。静的型付け重視である。
:[[Javaバイトコード]]を出力し、[[Java仮想マシン]]上で動作するJavaテクノロジ互換言語である。グローバル関数、グローバル変数の使用も容認されており、オブジェクト指向プログラミングを手続き型プログラミングのスタイルに崩したかのようにデザインされている。静的型付け重視である。
99行目: 99行目:
:[[JavaScript]]を強く意識してマイクロソフト社が開発したオブジェクト指向スクリプト言語。JavaScriptのプログラムを静的型付けで補完した言語である。[[クラスベース]]向けの構文と、[[関数型プログラミング]]の[[型システム]]のスタイルが加えられている。特に後者の性質が強調されている事から静的型付け重視である。継承構造によるサブタイプ多相はほぼ除外されており、パラメトリック多相とアドホック多相で[[抽象データ型]]を扱うという静的な型注釈とジェネリクス重視の言語設計になっている。オブジェクト指向ではあるが関数型の性格が強めである。
:[[JavaScript]]を強く意識してマイクロソフト社が開発したオブジェクト指向スクリプト言語。JavaScriptのプログラムを静的型付けで補完した言語である。[[クラスベース]]向けの構文と、[[関数型プログラミング]]の[[型システム]]のスタイルが加えられている。特に後者の性質が強調されている事から静的型付け重視である。継承構造によるサブタイプ多相はほぼ除外されており、パラメトリック多相とアドホック多相で[[抽象データ型]]を扱うという静的な型注釈とジェネリクス重視の言語設計になっている。オブジェクト指向ではあるが関数型の性格が強めである。
;[[Swift (プログラミング言語)|Swift]] 2014年
;[[Swift (プログラミング言語)|Swift]] 2014年
:[[Objective-C]]を発展させたものであるが、メッセージ構文は破棄されており、クラスベースのオブジェクト指向になっている。単一継承が採用されているが可視性にプロテクト指定が無いので縦の継承は軽視されている。代わに[[ミックスイン]]に分類されるプロトコルの多重実装を重視している。プロトコルで特徴付けられる[[インスタス]]の性質は[[ック]]で識別されコンパイル時と実行時双方の識別使い分けられる。多態性では動的束縛型(Opaque型)が重視されており、[[静的型付け]]のクラスと[[動的型付け]]の動的束縛型を併用する漸進的型付けの言語と言える。ジェネリクスも導入されている。
:[[Objective-C]]を発展させたものであるが、メッセージ構文は破棄されており、クラスベースのオブジェクト指向になっている。オブジェクトの[[イミュータブル|イミュータブル性]]が重視されている。単一継承が採用されているが可視性にプロテクト指定が無いので縦並びの継承は軽視されてプロトコルの横並びの多重実装を重視している。プロトコル[[インタフェー (抽象型)|インーフェース]][[ックイン]]の中間的機能あり、双方の短所解決する様々な仕組みが導入されてる。インスタンスはプロトコルを基準にして型類され、また抽象化される。プロトコルと[[ジェネリクス]]の連携による動的束縛型(Opaque型)の存在感高められており、それと[[静的型付け]]のクラスを併用する漸進的型付けの言語と言える。


== 用語と解説 ==
== 用語と解説 ==


==== [[クラス (コンピュータ)|クラス]] ====
==== [[クラス (コンピュータ)|クラス]] ====
クラスの仕組みを中心にしたオブジェクト指向を[[クラスベース]]と言う。クラスはデータメンバとメソッドをまとめたものであり、[[プログラム意味論|セマンティクス]]を付加された静的[[構造体|レコード]]とも解釈される。ここでのセマンティクスとはデータの用法を表わすメソッドを指す。クラスはインスタンスのひな型になる。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化はデータメンバとメソッドの可視性を指定する機能である。継承は自身のスーパークラスを指定する機能である。多態性はメソッドの抽象化と[[仮想関数テーブル]]を処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。
クラス(''class'')の仕組みを中心にしたオブジェクト指向を[[クラスベース]]と言う。クラスはデータメンバとメソッドをまとめたものであり、[[プログラム意味論|セマンティクス]]を付加された静的[[構造体|レコード]]とも解釈される。ここでのセマンティクスとはデータの用法を表わすメソッドを指す。クラスはインスタンスのひな型になる。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化はデータメンバとメソッドの可視性を指定する機能である。継承は自身のスーパークラスを指定する機能である。多態性はメソッドの抽象化と[[仮想関数テーブル]]を処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。


==== プロトタイプオブジェクト ====
==== プロトタイプオブジェクト ====
プロトタイプの仕組みを中心にしたオブジェクト指向を[[プロトタイプベース]]と言う。プロトタイプベースで言われるオブジェクトとは、中間参照ポインタの動的配列を指す。この動的配列は一般にフレームと呼ばれる。中間参照ポインタは一般にスロットと呼ばれる。スロットにはデータメンバとメソッドの参照が代入されるので、オブジェクトはクラスと同様にデータメンバとメソッドをまとめたものになる。オブジェクトはプロトタイプオブジェクトとオブジェクトに分かれる。前者はクラス、後者はインスタンスに当たるものである。前者はシステム提供プロトタイプとユーザー定義プロトタイプに分かれる。プログラマはシステム提供プロトタイプを派生させてユーザー定義プロトタイプを作成する。プロトタイプには、規定の設計に基づいたデータメンバ参照とメソッド参照が代入されており、オブジェクトのひな型になる。プロトタイプは親プロトタイプ参照用スロットを保持しており、これは継承と類似の機能になる。プロトタイプを複製する形式でオブジェクトは生成される。オブジェクトは複製元プロトタイプと同じデータメンバとメソッドを保持しているが、生成後は任意のデータメンバとメソッドを自由に付け替えできる。オブジェクトは複製元プロトタイプ参照用スロットを保持している。複製元プロトタイプからその親プロトタイプを辿れる参照のリンクによってオブジェクトは一定の体系化がなされている。
プロトタイプ(''prototype'')の仕組みを中心にしたオブジェクト指向を[[プロトタイプベース]]と言う。プロトタイプベースで言われるオブジェクトとは、中間参照ポインタの動的配列を指す。この動的配列は一般にフレームと呼ばれる。中間参照ポインタは一般にスロットと呼ばれる。スロットにはデータメンバとメソッドの参照が代入されるので、オブジェクトはクラスと同様にデータメンバとメソッドをまとめたものになる。オブジェクトはプロトタイプオブジェクトとオブジェクトに分かれる。前者はクラス、後者はインスタンスに当たるものである。前者はシステム提供プロトタイプとユーザー定義プロトタイプに分かれる。プログラマはシステム提供プロトタイプを派生させてユーザー定義プロトタイプを作成する。プロトタイプには、規定の設計に基づいたデータメンバ参照とメソッド参照が代入されており、オブジェクトのひな型になる。プロトタイプは親プロトタイプ参照用スロットを保持しており、これは継承と類似の機能になる。プロトタイプを複製する形式でオブジェクトは生成される。オブジェクトは複製元プロトタイプと同じデータメンバとメソッドを保持しているが、生成後は任意のデータメンバとメソッドを自由に付け替えできる。オブジェクトは複製元プロトタイプ参照用スロットを保持している。複製元プロトタイプからその親プロトタイプを辿れる参照のリンクによってオブジェクトは一定の体系化がなされている。


==== [[メッセージ (コンピュータ)|メッセージ]] ====
==== [[メッセージ (コンピュータ)|メッセージ]] ====
オブジェクト指向で言われるメッセージは、複数の方面の考え方が混同されている曖昧な用語になっている。元々はSmalltalkから始まったメッセージ構文ベースのオブジェクト指向の中心機構である。以前はクラスベースの方でもメソッドの呼び出しをメッセージを送るという風に考えることが推奨されていた。メッセージはオブジェクトのコミュニケーションと標榜されているが、その明確な利点はそれほど知られていないのが実情である。最も混同されているものに[[アクターモデル]]があるが、そこで言われる非同期性とオブジェクト指向で言われる評価の遅延性は似て異なるものである。コンポーネント準拠ソフトウェア工学と[[Object Request Broker|オブジェクトリクエストブローカー]]で言われる[[ソフトウェアコンポーネント]]同士の通信もメッセージパッシングと呼ばれることが多いが、その仕様と機能は動的ディスパッチに該当するものである。メッセージのオブジェクト指向的運用はメッセージングと名付けられている。その具体的な機能例は、Smalltalk、Objective-C、Selfの[[メッセージ転送|メッセージレシーバー]]と、Rubyのメソッドミッシングであるが、いずれもメッセージングの本質ではないとも言われている。
オブジェクト指向で言われるメッセージ(''message'')は、複数の方面の考え方が混同されている曖昧な用語になっている。元々はSmalltalkから始まったメッセージ構文ベースのオブジェクト指向の中心機構である。以前はクラスベースの方でもメソッドの呼び出しをメッセージを送るという風に考えることが推奨されていた。メッセージはオブジェクトのコミュニケーションと標榜されているが、その明確な利点はそれほど知られていないのが実情である。最も混同されているものに[[アクターモデル]]があるが、そこで言われる非同期性とオブジェクト指向で言われる評価の遅延性は似て異なるものである。コンポーネント準拠ソフトウェア工学と[[Object Request Broker|オブジェクトリクエストブローカー]]で言われる[[ソフトウェアコンポーネント]]同士の通信もメッセージパッシングと呼ばれることが多いが、その仕様と機能は動的ディスパッチに該当するものである。メッセージのオブジェクト指向的運用はメッセージングと名付けられている。その具体的な機能例は、Smalltalk、Objective-C、Selfの[[メッセージ転送|メッセージレシーバー]]と、Rubyのメソッドミッシングであるが、いずれもメッセージングの本質ではないとも言われている。


==== [[インスタンス]] ====
==== [[インスタンス]] ====
クラスベースではクラスを実体化したものであり、実装レベルで言うとデータメンバと仮想関数テーブルをメモリ上に展開したものになる。プロトタイプベースではプロトタイプオブジェクトのクローンで生成されたオブジェクトを指す。実装レベルで言うとメモリ上に展開された中間参照ポインタの動的配列になる。
(''instance'')はクラスベースではクラスを実体化したものであり、実装レベルで言うとデータメンバと仮想関数テーブルをメモリ上に展開したものになる。プロトタイプベースではプロトタイプオブジェクトのクローンで生成されたオブジェクトを指す。実装レベルで言うとメモリ上に展開された中間参照ポインタの動的配列になる。


==== [[フィールド (計算機科学)|データメンバ]] ====
==== [[フィールド (計算機科学)|データメンバ]] ====
クラスまたはオブジェクトに属する変数。言語によってフィールド、プロパティ、メンバ変数と呼ばれる。データメンバは、クラスデータメンバとインスタンスデータメンバに分かれる。クラスデータメンバは静的データメンバとも呼ばれる。その中で定数化されたものはクラス[[定数 (プログラミング)|定数]]と呼ばれる。クラスデータメンバはクラス名の名前空間でスコープされたグローバル変数と同じものであり、プログラム開始時から終了時まで確保される。インスタンスデータメンバはインスタンス生成時にメモリ上に確保されるものであり、その破棄時に消滅する。プロトタイプベースではプロトタイプオブジェクトが保持する特定のデータメンバが静的データメンバに該当するものになる。
(''data member'')はクラスまたはオブジェクトに属する変数。言語によってフィールド、プロパティ、メンバ変数と呼ばれる。データメンバは、クラスデータメンバとインスタンスデータメンバに分かれる。クラスデータメンバは静的データメンバとも呼ばれる。その中で定数化されたものはクラス[[定数 (プログラミング)|定数]]と呼ばれる。クラスデータメンバはクラス名の名前空間でスコープされたグローバル変数と同じものであり、プログラム開始時から終了時まで確保される。インスタンスデータメンバはインスタンス生成時にメモリ上に確保されるものであり、その破棄時に消滅する。プロトタイプベースではプロトタイプオブジェクトが保持する特定のデータメンバが静的データメンバに該当するものになる。


==== [[メソッド (計算機科学)|メソッド]] ====
==== [[メソッド (計算機科学)|メソッド]] ====
クラスまたはオブジェクトに属する関数。言語によってはメンバ関数とも呼ばれる。メソッドは、クラスメソッドとインスタンスメソッドに分かれる。クラスメソッドは静的メソッドとも呼ばれる。クラスメソッドはクラス名の名前空間でスコープされたグローバル関数と同じものである。インスタンスメソッドを呼び出すには、そのメソッドが属するインスタンス参照が必要になる。これはthisインスタンスと呼ばれる。プロトタイプベースではプロトタイプオブジェクトが保持する特定のメソッドが静的メソッドに該当するものになる。
(''method'')はクラスまたはオブジェクトに属する関数。言語によってはメンバ関数とも呼ばれる。メソッドは、クラスメソッドとインスタンスメソッドに分かれる。クラスメソッドは静的メソッドとも呼ばれる。クラスメソッドはクラス名の名前空間でスコープされたグローバル関数と同じものである。インスタンスメソッドを呼び出すには、そのメソッドが属するインスタンス参照が必要になる。これはthisインスタンスと呼ばれる。プロトタイプベースではプロトタイプオブジェクトが保持する特定のメソッドが静的メソッドに該当するものになる。


==== [[コンストラクタ]] ====
==== [[コンストラクタ]] ====
インスタンス生成時に呼び出されるそのクラスのメソッドである。インスタンスデータメンバを任意の値で初期化するためのものであるが、その他の初期化コードも記述できる。プロトタイプベースではプロトタイプオブジェクトと同名のグローバル関数として存在している。
(''constructor'')はインスタンス生成時に呼び出されるそのクラスのメソッドである。インスタンスデータメンバを任意の値で初期化するためのものであるが、その他の初期化コードも記述できる。プロトタイプベースではプロトタイプオブジェクトと同名のグローバル関数として存在している。


==== [[デストラクタ]] ====
==== [[デストラクタ]] ====
インスタンス破棄時に呼び出されるそのクラスのメソッドである。インスタンス破棄の影響を解決する任意の後始末コードを記述できる。インスタンスの破棄は占有メモリの解放を意味する。なお、ガーベジコレクタ実装言語ではファイナライザになっている事がある。プログラマが呼び出すデストラクタの方はその終了がメモリ解放に直結してるのに対し、ガーベジコレクタが呼び出すファイナライザの方はそうではない。
(''destructor'')はインスタンス破棄時に呼び出されるそのクラスのメソッドである。インスタンス破棄の影響を解決する任意の後始末コードを記述できる。インスタンスの破棄は占有メモリの解放を意味する。なお、ガーベジコレクタ実装言語ではファイナライザになっている事がある。プログラマが呼び出すデストラクタの方はその終了がメモリ解放に直結してるのに対し、ガーベジコレクタが呼び出すファイナライザの方はそうではない。


==== アクセスコントロール ====
==== アクセスコントロール ====
カプセル化に基づくデータメンバとメソッドの可視性を決定するものである。可視性はプライベート、プロテクト、パブリックの三種が基本である。プライベートは同クラス内のみ、プロテクトは同クラス内と派生クラス内のみ、パブリックはどこからでもアクセス可能である。
(''access control'')はカプセル化に基づくデータメンバとメソッドの可視性を決定するものである。可視性はプライベート、プロテクト、パブリックの三種が基本である。プライベートは同クラス内のみ、プロテクトは同クラス内と派生クラス内のみ、パブリックはどこからでもアクセス可能である。


==== [[インタフェース (抽象型)|インターフェース]] ====
==== [[インタフェース (抽象型)|インターフェース]] ====
プログラム概念と機能名の双方を指す用語である。言語によってはプロトコルと言われる。抽象メソッドと具象メソッド(実装内容付き)で構成される純粋抽象~半抽象クラスを意味する。クラスの振る舞い局面を抽出したものであり、[[統一モデリング言語|UML]]では実現と言われる。クラスによるインターフェースの継承は実装と呼ばれる。多重実装可が普通である。ミックスインとの違いは、抽象階層に焦点が当てられている事であり、直下の実装オブジェクトを共通の振る舞い局面でまとめることがその役割である。インターフェースは自身の実装オブジェクトをグループ化できる。{{仮リンク|記名的型付け|en|Nominal type system|label=}}に準拠しているのでインターフェースの実装の明記が振る舞い局面の識別基準になる。インターフェースは抽象メソッド主体なので多重継承時のメンバ名の重複はあまり問題にならない。共通の実装メソッドに集約されるからである。インターフェースはインスタンス化されない。
(''interface'')はプログラム概念と機能名の双方を指す用語である。言語によってはプロトコルと言われる。抽象メソッドと具象メソッド(実装内容付き)で構成される純粋抽象~半抽象クラスを意味する。クラスの振る舞い局面を抽出したものであり、[[統一モデリング言語|UML]]では実現と言われる。クラスによるインターフェースの継承は実装と呼ばれる。多重実装可が普通である。ミックスインとの違いは、抽象階層に焦点が当てられている事であり、直下の実装オブジェクトを共通の振る舞い局面でまとめることがその役割である。インターフェースは自身の実装オブジェクトをグループ化できる。{{仮リンク|記名的型付け|en|Nominal type system|label=}}に準拠しているのでインターフェースの実装の明記が振る舞い局面の識別基準になる。インターフェースは抽象メソッド主体なので多重継承時のメンバ名の重複はあまり問題にならない。共通の実装メソッドに集約されるからである。インターフェースはインスタンス化されない。


==== [[ミックスイン]] ====
==== [[ミックスイン]] ====
インターフェースに似たプログラム概念を指す用語である。機能名は言語によって[[トレイト]]またはプロトコルと言われる。抽象&具象メソッドとデータメンバで構成される継承専用クラスを意味する。クラスを特徴付けるための装飾部品である。クラスによるトレイトの継承は実装と呼ばれる。多重実装可が普通である。インターフェースとの違いは、トレイトの実装階層に焦点が当てられている事であり、オブジェクトを所有メンバで特定してまとめることがその役割である。トレイトは自身の[[上位集合]]であるオブジェクトをグループ化できる。{{仮リンク|構造的型付け|en|Structural type system|label=}}に準拠しているので所属メンバ構成自体がトレイト等価性の識別基準になる。これはトレイト実装を明記してなくても、そのトレイトが内包する全メンバを所持していれば同じトレイトと見なされることを意味する。トレイトは多重継承時のメンバ名重複の際にその参照の優先順位に注意する必要が出てくる。トレイトはインスタンス化されない。
(''mixin'')はインターフェースに似たプログラム概念を指す用語である。機能名は言語によって[[トレイト]]またはプロトコルと言われる。抽象&具象メソッドとデータメンバで構成される継承専用クラスを意味する。クラスを特徴付けるための装飾部品である。クラスによるトレイトの継承は実装と呼ばれる。多重実装可が普通である。インターフェースとの違いは、トレイトの実装階層に焦点が当てられている事であり、オブジェクトを所有メンバで特定してまとめることがその役割である。トレイトは自身の[[上位集合]]であるオブジェクトをグループ化できる。{{仮リンク|構造的型付け|en|Structural type system|label=}}に準拠しているので所属メンバ構成自体がトレイト等価性の識別基準になる。これはトレイト実装を明記してなくても、そのトレイトが内包する全メンバを所持していれば同じトレイトと見なされることを意味する。トレイトは多重継承時のメンバ名重複の際にその参照の優先順位に注意する必要が出てくる。トレイトはインスタンス化されない。


==== [[メタクラス]] ====
==== [[メタクラス]] ====
143行目: 143行目:


==== 遅延バインディング ====
==== 遅延バインディング ====
遅延バインディング(''late binding'')動的バインディングほぼ同じ意味で用いられてい前者は特にリフレクション機能を通して実装される方をす。抽象化された型に対して、実行時の文字列(char配列やString)を内部識別子に解釈し、コンパイル時には認識されていなかったオブジェクトをローディングして代入する仕組みなどである。オブジェクトの呼び出しが、[[ダイナミックリンクライブラリ|DLL]]やクラスライブラリの動的ローディングに繋がることが遅延バインディングと呼ばれる基準になる。[[ストアドプロシージャ]]の動的ロード、代入、呼び出しもそれに当たる。ローディング基準が外される例では、プログラム内でデータとして扱われている[[コードブロック]]を関数の型に代入して呼び出すという仕組みがある。そのコードブロックは文字値と数値の混合配列であり、リフレクション機能を利用して実行する。
(''late binding'')は、識別子が参照するオブジェクトをコンパイル時に決める事前バインディング(''early binding'')の対義語であり、この場合は識別子の参照先を実行時に決める動的バインディングほぼ同じ意味で用いられる。一方で、特にリフレクション機能を通して実装される方を遅延バインディングとる考え方もある。抽象化された型に対して、実行時の文字列(char配列やString)を内部識別子に解釈し、コンパイル時には認識されていなかったオブジェクトをローディングして代入する仕組みなどである。オブジェクトの呼び出しが、[[ダイナミックリンクライブラリ|DLL]]やクラスライブラリの動的ローディングに繋がることが遅延バインディングと呼ばれる基準になる。[[ストアドプロシージャ]]の動的ロード、代入、呼び出しもそれに当たる。ローディング基準が外される例では、プログラム内でデータとして扱われている[[コードブロック]]を関数の型に代入して呼び出すという仕組みがある。そのコードブロックは文字値と数値の混合配列であり、リフレクション機能を利用して実行する。


==== 動的ディスパッチ ====
==== 動的ディスパッチ ====
157行目: 157行目:
== 関連項目 ==
== 関連項目 ==
{{Wikibooks|オブジェクト指向|オブジェクト指向}}
{{Wikibooks|オブジェクト指向|オブジェクト指向}}
*[[委譲]]
* [[オブジェクト指向]]
* [[クラス (コンピュータ)]]
* [[メッセージ (コンピュータ)]]
* [[インスタンス]]
* [[フィールド (計算機科学)]]
* [[メソッド (計算機科学)]]
* [[インスタンス変数]]
* [[クラス変数]]
* [[カプセル化]]
* [[継承 (プログラミング)|継承]]
* [[多態性]]
* [[委譲]]


{{Normdaten}}
{{Normdaten}}

2020年8月6日 (木) 20:14時点における版

オブジェクト指向プログラミング(オブジェクトしこうプログラミング、: object-oriented programming、略語:OOP)とは、互いに密接な関連性を持つデータメソッドをひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定義と、それらオブジェクトを相互に作用させる様々なプロセスの設定を通して、プログラム全体を構築するソフトウェア開発手法である。

オブジェクト指向という用語自体は、計算機科学者アラン・ケイによって生み出されている。1967年公開の言語「Simula67」の設計に印象を受けたケイが咄嗟に口にしたとされるこの造語は、彼が1972年から公開を始めた「Smalltalk」の言語設計を説明する中で初めて世間に発信された。なお、ケイが示したメッセージパッシングを中心にするオブジェクト指向は広く認知される事はなく、オブジェクトというプログラム概念を注目させるだけに留まっている。同時にケイの手から離れたオブジェクト指向は抽象データ型を中心にした解釈へと推移していき、1983年に計算機科学者ビャーネ・ストロヴストルップが公開した「C++」が契機になって、日本では一般にOOPの三大要素と呼ばれるカプセル化継承多態性といったパラダイムが確立されている。

特徴

現行のオブジェクト指向プログラミングは事実上、1974年に計算機科学者バーバラ・リスコフらが提唱した抽象データ型を基礎的な考え方にする方向性で定着している。抽象データ型のプログラム実装スタイルを具体的に規定したものが1~3であり、日本では一般に三大要素と呼ばれている。これに沿った言語仕様を備えたプログラミング言語がオブジェクト指向準拠と判別されている。4と5は、アラン・ケイが重視する元祖的なコンセプトであり現在では主流から外れているが、オブジェクト指向の源流思想として蛇足ながら紹介を加える。

  1. カプセル化encapsulation
  2. 継承inheritance
  3. 多態性polymorphism
  4. メッセージパッシングmessage passing
  5. 遅延バインディングlate binding

カプセル化

一定の関連性を持つデータ(変数、プロパティ、フィールド)と、それらを操作するメソッドをひとまとめにしてオブジェクトとし、外部に対して必要とされるデータとメソッドのみを公開し、それ以外を内部に隠蔽する仕組みがカプセル化と呼ばれる。公開されたデータは外部のメソッドから直接参照ないし変更する事できる。公開されたメソッドは外部のメソッドから直接呼び出す事ができる。隠蔽されたデータとメソッドは外部からアクセスできず、これは情報隠蔽と呼ばれる。メソッドを通してデータを参照ないし変更する仕組みはデータの抽象化を表現する。データを参照するメソッドはゲッターまたはアクセッサ、データを変更するメソッドはセッターまたはミューテイタと呼ばれる。

継承

既存オブジェクトのデータ構成とメソッド構成を引き継いで、新しい派生オブジェクトを定義する仕組みが継承と呼ばれる。引き継ぐ際には新たなデータとメソッドを自由に追加できるので、派生オブジェクトの構成は既存内容+追加内容になる。既存オブジェクトは親オブジェクト、派生オブジェクトは子オブジェクトとも呼ばれる。クラスベースでは、親をスーパークラス、子をサブクラスと呼ぶ。一つのスーパークラスを継承するのは単一継承と呼ばれる。複数個のスーパークラスを継承してそれぞれの構成内容を引き継ぐのは多重継承と呼ばれる。抽象化に注目した継承の方は、UMLでは実現と呼ばれるものになる。これは一定のオブジェクトに共通した振る舞い局面を抜き出して抽象化する仕組みを指し、その抽象化オブジェクトはインターフェーストレイト、プロトコルなどと呼ばれる。

多態性

異なる種類のオブジェクトに同一の操作インターフェースを持たせる仕組みが多態性と呼ばれる。オブジェクト指向視点の多態性は、クラスの派生関係またはオブジェクトの動的バインディングによって、コンパイル時のメソッド名から呼び出されるプロセス内容が実行時に決定されるという機構を意味するサブタイプ多相英語版を指す。サブタイプ多相は仮想関数英語版多重ディスパッチ動的ディスパッチ英語版の三手法に分類される。最もよく知られる仮想関数は多態性と同義に説明される事が多い。仮想関数は、メソッドが所属するクラスの派生関係のみに焦点を当てたシングルディスパッチであり、スーパークラス抽象メソッドへの呼び出しから、それをオーバーライドしたサブクラス実装メソッドに分岐させる機能を指す。その際は各メソッドへのポインタを連ねた仮想呼出テーブルと呼ばれる仕組みが用いられる。多重ディスパッチは、メソッドが所属するクラスの派生関係に加えて、メソッドの各引数のクラスの派生関係にも注目した形態である。各引数は実行時に型ダウンキャストされて、それらの引数型の組み合わせに対応したプロセスに分岐する。メソッド所属クラスの派生関係が絡まない場合は単一引数だとシングルディスパッチになる。多重ディスパッチの中でもプロセス分岐に関与するクラスが二つに限定されたものはダブルディスパッチと個別定義されている。サブタイプ多相における動的ディスパッチは、プロトタイプベースのオブジェクトのメソッド名スロットに差し込まれる実体メソッド参照が随時切り替えられることで、そのメソッド名から呼び出されるプロセスが実行時に決定されるという仕組みを指す。クラスベースの方ではリフレクション機能によって同様に、メソッド名から呼び出されるプロセス内容が実行時に決まるという仕組みが実装される。

メッセージパッシング

I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages. (さながら生物の細胞、もしくはネットワーク上の銘々のコンピュータ、それらはただメッセージによって繋がり合う存在、僕はオブジェクトをそう考えている) — Alan Kay
... each object could have several algebras associated with it, and there could be families of these, and that these would be very very useful. (銘々のオブジェクトは自身に伴う幾つかの「代数」を持つ、またそれらの家族たちもいるかもしれない、それらは極めて有用になるだろう) — Alan Kay
The Japanese have a small word - ma ... The key in making great and growable systems is much more to design how its modules communicate rather than what their internal properties and behaviors should be. (日本語には「間」という言葉がある・・・成長的なシステムを作る鍵とは内部の特徴と動作がどうあるべきかよりも、それらがどう繋がり合うかをデザインする事なんだ) — Alan Kay

遅延バインディング

I realized that the cell/whole-computer metaphor would get rid of data, ... (僕はこう気付いた、細胞であり全体でもあるコンピュータメタファーはデータを除去するであろうと、) — Alan Kay
... 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.Simulaを触媒にした二本の道筋があった。初めの一本は細胞組織的な非データ手法、僕が選んだ方だ。少し遅れたもう一本は抽象データ型、こっちの方がずっと賑わってるね。) — Alan Kay

歴史

オブジェクト指向プログラミングという考え方が生まれた背景には、計算機の性能向上によって従来より大規模なソフトウェアが書かれるようになってきたということが挙げられる。大規模なソフトウェアが書かれコードも複雑化してゆくにつれ、ソフトウェア開発コストが上昇し、1960年代には「ソフトウェア危機 (software crisis)」といったようなことも危惧されるようになってきた。そこでソフトウェアの再利用部品化といったようなことを意識した仕組みの開発や、ソフトウェア開発工程の体系化(ソフトウェア工学 (software engineering) の誕生)などが行われるようになった。

このような流れの中で、プログラムを構成するコードとデータのうち、コードについては手続き関数といった仕組みを基礎に整理され、その構成単位をブラックボックスとすることで再利用性を向上し、部品化を推進する仕組みが提唱され構造化プログラミング (structured programming) として1967年[要出典]エドガー・ダイクストラ (Edsger Wybe Dijkstra) らによってまとめあげられた(プログラミング言語の例としてはPascal 1971年)。なお、それに続けて「しかしデータについては相変わらず主記憶上の記憶場所に置かれている限られた種類の基本データ型の値という比較的低レベルの抽象化から抜け出せなかった。これはコードはそれ自身で意味的なまとまりを持つがデータはそれを処理するコードと組み合わせないと十分に意味が表現できないという性質があるためであった。」といったように、ほぼ間違いなく説明されている。

そこでデータを構造化し、ブラックボックス化するために考え出されたのが、データ形式の定義とそれを処理する手続きや関数をまとめて一個の構成単位とするという考え方でモジュール (module) と呼ばれる概念である(プログラミング言語の例としてはModula-2 1979年)。しかし定義とプログラム内の実体が一対一に対応する手続きや関数とは異なり、データはその形式の定義に対して値となる実体(インスタンスと呼ばれる)が複数存在し、各々様々な寿命を持つのが通例であるため、そのような複数の実体をうまく管理する枠組みも必要であることがわかってきた。そこで単なるモジュールではなく、それらのインスタンスを整理して管理する仕組み(例えばクラスとその継承など)まで考慮して生まれたのがオブジェクトという概念である(プログラミング言語の例としては1967年のSimula 67)。

Simulaのオブジェクトとクラスというアイデアは異なる二つの概念に継承される。一つはシステム全てをオブジェクトの集合と捉え、オブジェクトの相互作用をメッセージに喩えた「オブジェクト指向」である。オブジェクト間の相互作用をメッセージの送受と捉えることで、オブジェクトは受信したメッセージに見合った手続き単位(≒関数)を自身で起動すると考える。結果オブジェクトは自身の持つ手続きのカプセル化を行うことができ、メッセージが同じでもレシーバオブジェクトによって行われる手続きは異なる――多相性(ポリモーフィズム)を実現した(このメッセージを受け実行される手続き単位は、メッセージで依頼されたことを行うための「手法」の意味でメソッドと呼ばれる)。この思想に基づき作られたのがSmalltalk1972年)であり、オブジェクト指向という言葉はこのときアラン・ケイによって作られた。

一方、Smalltalkとは別にSimulaの影響を受け作られたC++1979年)は抽象データ型のスーパーセットとしてのクラス、オブジェクトに注目し、オブジェクト指向をカプセル化、継承、多相性をサポートするものと再定義した(その際、実行時速度重視およびコンパイラ設計上の制約により、変数メタファである動的束縛の特徴は除外された)。これらは当初抽象データ型派生仮想関数と呼ばれ、オブジェクトのメンバ関数を実体ではなくポインタとすることで、継承関係にあるクラスのメンバ関数のオーバーライド(上書き)を可能にしたことで、多相性を実現した(この流儀ではメッセージメタファはオブジェクト指向に必須ではないものと定義し、オブジェクトの持つ手続きをメソッドとは呼ばずメンバ関数と呼ぶ)。この他、Smalltalkにある動的束縛の類似的な機能としてオーバーロード(多重定義)が実装されている。

Smalltalkはこの「全てをオブジェクトとその相互作用で表現する」というデザインに立ち設計されたため、全てをファイルと捉えるファイル指向オペレーティングシステムからの脱却と、プログラムをフロー制御された手続きと捉える手続き型言語からの脱却が行われた。そのためSmalltalkは自身がオブジェクト指向オペレーティングシステムでもあること、メッセージ・パッシングなどの特徴を持った。これは当時のプログラム言語としては特異的であり、ガベージコレクタを必要とし、高度な最適化が試される前のバイトコードインタプリタで実行される処理の重さも手伝って先進的ではありながら普及しがたいものであると捉えられた。また、メッセージでの多相性は、変数へのオブジェクトの動的束縛が前提となるため、静的型チェック機構でのサポートが難しく、C++等の実行時性能重視の言語にとって実装から除外すべき特徴となった。

C++の創始者ビャーネ・ストロヴストルップは、Smalltalkが目指したある種の理想の追求には興味が無く、現用としての実用性を重視した。そのため、C++の再定義した「オブジェクト指向」は既存言語の拡張としてオブジェクト指向機能を実装できることでブレイクスルーを迎え急速に普及する。Smalltalkが単なるメソッドの動的呼び出しをメッセージ送信に見立て、呼び出すメソッドが見つからないときのみメッセージをハンドリングできるようにした「省コスト版」の機構を発明し以降それを採用するに至った経緯も手伝って、メッセージ送信という考え方はやや軽視されるようになり、オブジェクト指向とはC++の再定義したものと広く認知されるようになった。

1980年代後半に次々と生まれたオブジェクト指向分析・設計論は、Smalltalkを源流とするオブジェクト指向を基に組み立てられた。そのころSmalltalkは商用展開こそされていたが広く普及しているとは言えず、一般にはC++での実装が多くを占めた。しかしC++はSmalltalkと思想的にかなり異なる点や、同様のことを実現する際の実装面での複雑さや制約が問題とされた。このニーズを受けC++の提示した抽象データ型にクラスを適用する現実的な考え方と親しまれたALGOL系の構文を踏襲しつつ、内部的には柔軟なSmalltalkのオブジェクトモデルを採用し、メソッドなどの一部用語やリフレクション、実行時動的性などSmalltalk色も取り入れたJavaが注目を集めた(1995年に登場。元々はモバイル機器向け言語処理系として開発された)。程なくSmalltalkやSELFで達成された仮想マシン(バイトコードインタープリタ)高速化技術の転用により実用的速度を得、バランス感覚に長けたJavaの台頭によってオブジェクト指向開発に必要な要素の多くが満たされ、1990年代後半からオブジェクト指向は広く普及するようになった。

代表的なオブジェクト指向言語

オブジェクト指向言語は、抽象データ型の型コンストラクタの仕組みに倣ったクラスベースレコードへの動的バインディングの仕組みに倣ったプロトタイプベースSmalltalkをルーツにしたメッセージ構文ベースの三タイプに分類されるのが一般的である。クラスベースでは「C++」「Java」「C#」が代表的である。プロトタイプベースでは「Python」「JavaScript」「Ruby」が有名である。メッセージ構文ベースでは「Smalltalk」「Objective-C」「Self」などがある。言語仕様の中でオブジェクト指向の存在感が比較的高い代表的なプログラミング言語は以下の通りである。

Simula 67 1967年
1962年に公開されたSimulaの後継版であり、クラスのプログラム概念を導入した最初の言語である。現実世界の擬似モデルを観測するシミュレーション・プログラム制作用に開発されたもので、クラスをメモリに展開したオブジェクトは、その観測対象要素になった。Simulaのクラスは、プロシージャに専用変数と専用サブルーチンを付与したミニモジュールと言えるものであったが、継承と仮想関数という先進的な設計を備えていた事でオブジェクト指向言語の草分けと見なされるようになった。クラスベースの源流である。
Smalltalk 1972年
メッセージパッシングのプログラム概念を導入した最初の言語。数値、真偽値、文字列から変数、コードブロック、メタデータまでのあらゆる要素をオブジェクトとするアイディアを編み出した最初の言語でもある。オブジェクト指向という言葉はSmalltalkの言語設計を説明する中で生み出された。オブジェクトにメッセージを送るという書式であらゆるプロセスを表現することが目標にされている。メッセージレシーバー委譲の仕組みは、形式化されてない動的ディスパッチと動的バインディング相当のものでありプロトタイプベースの源流になった。専用のランタイム環境上で動作させる設計は、実行時多態性とセキュリティにも繋がるモニタリングを実現した。これは後に仮想マシン仮想実行システムと呼ばれるものになる。
C++ 1983年
C言語クラスベースのオブジェクト指向を追加したもの。Simulaの影響を受けている。静的型付けクラスが備えられて、カプセル化、継承、多態性の三仕様を実装している。カプセル化はフレンド指定で寛容化されている。継承は多重継承可能であり継承の可視性も存在し菱形継承問題解決用の仮想継承も導入されている。多態性は仮想関数によるサブタイプ多相、テンプレートクラス&関数によるパラメトリック多相、関数&演算子オーバーロードによるアドホック多相が導入されている。元がC言語であるため、オブジェクト指向から逸脱したコーディングも多用できる点が物議を醸したが、その是非はプログラマ次第であるという結論に落ち着いた。
Objective-C 1984年
C言語メッセージ構文ベースのオブジェクト指向を追加したもの。こちらはSmalltalkの影響を受けており、それに準じたメッセージパッシングの書式が備えられた。メッセージを受け取るクラスの定義による静的型付けと共に、メッセージを委譲するオブジェクトの実行時決定による動的型付けも設けられている。オブジェクト指向的にはC++よりも正統と見なされた。制御構造文が追加され、メッセージを送る書式も平易化されており、Smalltalkよりも扱いやすくなった。
Object Pascal 1986年
Pascalにクラスベースのオブジェクト指向を追加したもの。厳格なカプセル化、単一のみの継承、仮想関数と多重実装可なインターフェースによる多態性といった基本に忠実な静的型付け重視である。関数&演算子オーバーロード(アドホック多相)とジェネリクス(パラメトリック多相)は除外された。
Eiffel 1986年
C++の柔軟性と融通性とは正反対のオブジェクト指向言語。クラスベース静的型付け重視である。契約プログラミングを理念にしており、アサーションの挿入でクラスの状態とメソッド引数&返り値を細かくチェックできる。クラスメンバ(フィーチャー)は属性、アクセッサ、ミューテイタの三種限定でオーバーロードはできない。カプセル化の可視性は自身に依存するクラス(クライアント)を定義するという形で決められる。多重継承可能であり、クラス間の繋がりを仮想継承機能、各種オーバーライド指定子、名前衝突を解決するリネーミング機能などで綿密に設定できる。仮想関数、ジェネリッククラスも導入されている。ガーベジコレクション機能が初めて導入されたオブジェクト指向言語でもある。
Self 1987年
メッセージ構文ベースのオブジェクト指向言語。標準配備のオブジェクトを複製して、そのスロットに任意のプロパティとメソッドを動的バインディングできるというプロトタイプベースを初めて導入したオブジェクト指向言語でもある。ゆえに動的型付け重視である。Smalltalkと同様に専用のランタイム環境で実行されたが、これも実用面では初となる実行時コンパイラjust-in-time compiler)機能が備えられて速度面でも画期的なものになった。
CLOS 1988年
Common Lispプロトタイプベースに似たオブジェクト指向を追加したもの。データオブジェクトとメソッドオブジェクトに分離されており、前者のスロットには任意の変数を、後者のスロットには任意の関数を動的バインディングできる動的型付け重視である。動的型付けのデータオブジェクトを引数にしたメソッドによる多重ディスパッチが重視されている。
Python 1994年
プロトタイプベースクラスベースの双方を兼ねたオブジェクト指向スクリプト言語。静的型付けのクラスと動的型付けのインスタンスが併用されているが、後者の動的バインディングの比重が大きめである。ダックタイピングを重視する方針により型宣言制約が撤廃されている。多態性は動的ディスパッチを中心にし、メソッドシグネチャと関数プロトタイプを操作できるリフレクションによって更に柔軟性が図られている。これらにより動的型付け重視である。ジェネリッククラスとジェネリック関数も導入されており、動的な柔軟性と静的な多様性の双方を使い分けられる。構文と書式を比較的簡素化し、インタプリタ式動作なので堅牢性も高い。
Java 1995年
C++をモデルにしつつ堅牢性とセキュリティを重視したクラスベースのオブジェクト指向言語。静的型付け重視である。パッケージ中心のカプセル化、単一のみの継承、仮想関数と多重実装可なインターフェースによる多態性と、基本に忠実なクラスベースである。メソッドオーバーロードと、クラスメタデータを操作できるリフレクションは初期から採用された。データコンテナ系のクラスと関数型インターフェースなどに限ってジェネリッククラスが導入されている。C++のポインタと値型インスタンスと演算子オーバーロードは真っ先に除外され、例外処理は残された。仮想マシン上で実行される。仮想マシンガーベジコレクションの技術は比較的高度と見なされている。
Delphi 1995年
Object Pascalを発展させたもの。それと同様にこちらも基本に忠実なクラスベースで静的型付け重視であった。当初はデータベース操作プログラム開発を主な用途にして公開された。クラスとレコード(構造体)に同等の比重が置かれていた。一時期Javaの対抗馬になった。
Ruby 1995年
Pythonを意識して開発されたオブジェクト指向スクリプト言語。Smalltalkを一つの理想にして動的型付けを重視している。日本で誕生してグローバル化したプログラミング言語である。LISPとSmalltalkのメタプログラミング的なオブジェクト指向から、PythonとJavaScriptのプロトタイプベースなオブジェクト指向までのスタイルを幅広く取り入れており、様々な有用なプログラミング手法を採用している技のデパートのような言語である。構文と書式は平易性を旨としている。
JavaScript 1996年
Smalltalkの思想を受け継いでデザインされたオブジェクト指向スクリプト言語。当初はWEBアプリケーション開発を主な用途にして公開された。プロトタイプベースであり、オブジェクトを純然たるスロットの集合体として定義している。スロットにはプロパティとメソッドが動的バインディングされ、ダックタイピングで型識別される。この仕組みによる動的型付けが本命にされて、プリミティブ型以外の静的型付けが放棄されている。オブジェクトはプロトタイプのクローンであり、そのプロトタイプで分類される。プロトタイプの方は継承で体系化されている。ECMAScriptとして標準化されている。2015年版からはクラスベース向けの構文もサポートするようになった。
C# 2000年
Javaを強く意識してマイクロソフト社が開発したクラスベースのオブジェクト指向言語。C++のクラスの性質を残しながらマルチパラダイムに発展させている。拡張メソッドや演算子オーバーロードなどのアドホック多相的なコーディングサポートが豊富である。パラメトリック多相は型変数の共変性と反変性、型引数への型制約指定を備えている。サブタイプ多相は、クラスは単一継承でインターフェースは多重実装と基本通りである。数々の関数型プログラミング機能も導入されている。基本は静的型付けであるが、動的束縛型(dynamic型)とダックタイピングによる動的型付けの存在感が高められているので、漸進的型付けの言語と見なされている。.NET Framework共通言語基盤=仮想実行システム)上で実行される。
Scala 2003年
クラスベースのオブジェクト指向と関数型プログラミングを融合させた言語。抽象データ型と、関数型の型システムに同等の比重が置かれており静的型付け重視である。パラメトリック多相とサブタイプ多相を連携させたバリアンスによる多態性が重視されている。型変数の継承関係による共変性と反変性で結ばれた、ミックスインに分類されるトレイトの実装によって派生型付けされたオブジェクトは立体的に体系化される。型引数はアドホック多相に該当する型境界で制約されて静的な型チェックをサポートする。イミュータブルなオブジェクト生成と、オブジェクトのパターンマッチング式の導入も特徴である。
Kotlin 2011年
Javaバイトコードを出力し、Java仮想マシン上で動作するJavaテクノロジ互換言語である。グローバル関数、グローバル変数の使用も容認されており、オブジェクト指向プログラミングを手続き型プログラミングのスタイルに崩したかのようにデザインされている。静的型付け重視である。
TypeScript 2012年
JavaScriptを強く意識してマイクロソフト社が開発したオブジェクト指向スクリプト言語。JavaScriptのプログラムを静的型付けで補完した言語である。クラスベース向けの構文と、関数型プログラミング型システムのスタイルが加えられている。特に後者の性質が強調されている事から静的型付け重視である。継承構造によるサブタイプ多相はほぼ除外されており、パラメトリック多相とアドホック多相で抽象データ型を扱うという静的な型注釈とジェネリクス重視の言語設計になっている。オブジェクト指向ではあるが関数型の性格が強めである。
Swift 2014年
Objective-Cを発展させたものであるが、メッセージ構文は破棄されており、クラスベースのオブジェクト指向になっている。オブジェクトのイミュータブル性が重視されている。単一継承が採用されているが可視性にプロテクト指定が無いので縦並びの継承は軽視されており、プロトコルの横並びの多重実装を重視している。プロトコルはインターフェースミックスインの中間的機能であり、双方の短所を解決する様々な仕組みが導入されている。インスタンスはプロトコルを基準にして型分類され、また抽象化される。プロトコルとジェネリクスの連携による動的束縛型(Opaque型)の存在感が高められており、それと静的型付けのクラスを併用する漸進的型付けの言語と言える。

用語と解説

クラス(class)の仕組みを中心にしたオブジェクト指向をクラスベースと言う。クラスはデータメンバとメソッドをまとめたものであり、セマンティクスを付加された静的レコードとも解釈される。ここでのセマンティクスとはデータの用法を表わすメソッドを指す。クラスはインスタンスのひな型になる。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化はデータメンバとメソッドの可視性を指定する機能である。継承は自身のスーパークラスを指定する機能である。多態性はメソッドの抽象化と仮想関数テーブルを処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。

プロトタイプオブジェクト

プロトタイプ(prototype)の仕組みを中心にしたオブジェクト指向をプロトタイプベースと言う。プロトタイプベースで言われるオブジェクトとは、中間参照ポインタの動的配列を指す。この動的配列は一般にフレームと呼ばれる。中間参照ポインタは一般にスロットと呼ばれる。スロットにはデータメンバとメソッドの参照が代入されるので、オブジェクトはクラスと同様にデータメンバとメソッドをまとめたものになる。オブジェクトはプロトタイプオブジェクトとオブジェクトに分かれる。前者はクラス、後者はインスタンスに当たるものである。前者はシステム提供プロトタイプとユーザー定義プロトタイプに分かれる。プログラマはシステム提供プロトタイプを派生させてユーザー定義プロトタイプを作成する。プロトタイプには、規定の設計に基づいたデータメンバ参照とメソッド参照が代入されており、オブジェクトのひな型になる。プロトタイプは親プロトタイプ参照用スロットを保持しており、これは継承と類似の機能になる。プロトタイプを複製する形式でオブジェクトは生成される。オブジェクトは複製元プロトタイプと同じデータメンバとメソッドを保持しているが、生成後は任意のデータメンバとメソッドを自由に付け替えできる。オブジェクトは複製元プロトタイプ参照用スロットを保持している。複製元プロトタイプからその親プロトタイプを辿れる参照のリンクによってオブジェクトは一定の体系化がなされている。

オブジェクト指向で言われるメッセージ(message)は、複数の方面の考え方が混同されている曖昧な用語になっている。元々はSmalltalkから始まったメッセージ構文ベースのオブジェクト指向の中心機構である。以前はクラスベースの方でもメソッドの呼び出しをメッセージを送るという風に考えることが推奨されていた。メッセージはオブジェクトのコミュニケーションと標榜されているが、その明確な利点はそれほど知られていないのが実情である。最も混同されているものにアクターモデルがあるが、そこで言われる非同期性とオブジェクト指向で言われる評価の遅延性は似て異なるものである。コンポーネント準拠ソフトウェア工学とオブジェクトリクエストブローカーで言われるソフトウェアコンポーネント同士の通信もメッセージパッシングと呼ばれることが多いが、その仕様と機能は動的ディスパッチに該当するものである。メッセージのオブジェクト指向的運用はメッセージングと名付けられている。その具体的な機能例は、Smalltalk、Objective-C、Selfのメッセージレシーバーと、Rubyのメソッドミッシングであるが、いずれもメッセージングの本質ではないとも言われている。

instance)はクラスベースではクラスを実体化したものであり、実装レベルで言うとデータメンバと仮想関数テーブルをメモリ上に展開したものになる。プロトタイプベースではプロトタイプオブジェクトのクローンで生成されたオブジェクトを指す。実装レベルで言うとメモリ上に展開された中間参照ポインタの動的配列になる。

data member)はクラスまたはオブジェクトに属する変数。言語によってフィールド、プロパティ、メンバ変数と呼ばれる。データメンバは、クラスデータメンバとインスタンスデータメンバに分かれる。クラスデータメンバは静的データメンバとも呼ばれる。その中で定数化されたものはクラス定数と呼ばれる。クラスデータメンバはクラス名の名前空間でスコープされたグローバル変数と同じものであり、プログラム開始時から終了時まで確保される。インスタンスデータメンバはインスタンス生成時にメモリ上に確保されるものであり、その破棄時に消滅する。プロトタイプベースではプロトタイプオブジェクトが保持する特定のデータメンバが静的データメンバに該当するものになる。

method)はクラスまたはオブジェクトに属する関数。言語によってはメンバ関数とも呼ばれる。メソッドは、クラスメソッドとインスタンスメソッドに分かれる。クラスメソッドは静的メソッドとも呼ばれる。クラスメソッドはクラス名の名前空間でスコープされたグローバル関数と同じものである。インスタンスメソッドを呼び出すには、そのメソッドが属するインスタンス参照が必要になる。これはthisインスタンスと呼ばれる。プロトタイプベースではプロトタイプオブジェクトが保持する特定のメソッドが静的メソッドに該当するものになる。

constructor)はインスタンス生成時に呼び出されるそのクラスのメソッドである。インスタンスデータメンバを任意の値で初期化するためのものであるが、その他の初期化コードも記述できる。プロトタイプベースではプロトタイプオブジェクトと同名のグローバル関数として存在している。

destructor)はインスタンス破棄時に呼び出されるそのクラスのメソッドである。インスタンス破棄の影響を解決する任意の後始末コードを記述できる。インスタンスの破棄は占有メモリの解放を意味する。なお、ガーベジコレクタ実装言語ではファイナライザになっている事がある。プログラマが呼び出すデストラクタの方はその終了がメモリ解放に直結してるのに対し、ガーベジコレクタが呼び出すファイナライザの方はそうではない。

アクセスコントロール

access control)はカプセル化に基づくデータメンバとメソッドの可視性を決定するものである。可視性はプライベート、プロテクト、パブリックの三種が基本である。プライベートは同クラス内のみ、プロテクトは同クラス内と派生クラス内のみ、パブリックはどこからでもアクセス可能である。

interface)はプログラム概念と機能名の双方を指す用語である。言語によってはプロトコルと言われる。抽象メソッドと具象メソッド(実装内容付き)で構成される純粋抽象~半抽象クラスを意味する。クラスの振る舞い局面を抽出したものであり、UMLでは実現と言われる。クラスによるインターフェースの継承は実装と呼ばれる。多重実装可が普通である。ミックスインとの違いは、抽象階層に焦点が当てられている事であり、直下の実装オブジェクトを共通の振る舞い局面でまとめることがその役割である。インターフェースは自身の実装オブジェクトをグループ化できる。記名的型付け英語版に準拠しているのでインターフェースの実装の明記が振る舞い局面の識別基準になる。インターフェースは抽象メソッド主体なので多重継承時のメンバ名の重複はあまり問題にならない。共通の実装メソッドに集約されるからである。インターフェースはインスタンス化されない。

mixin)はインターフェースに似たプログラム概念を指す用語である。機能名は言語によってトレイトまたはプロトコルと言われる。抽象&具象メソッドとデータメンバで構成される継承専用クラスを意味する。クラスを特徴付けるための装飾部品である。クラスによるトレイトの継承は実装と呼ばれる。多重実装可が普通である。インターフェースとの違いは、トレイトの実装階層に焦点が当てられている事であり、オブジェクトを所有メンバで特定してまとめることがその役割である。トレイトは自身の上位集合であるオブジェクトをグループ化できる。構造的型付け英語版に準拠しているので所属メンバ構成自体がトレイト等価性の識別基準になる。これはトレイト実装を明記してなくても、そのトレイトが内包する全メンバを所持していれば同じトレイトと見なされることを意味する。トレイトは多重継承時のメンバ名重複の際にその参照の優先順位に注意する必要が出てくる。トレイトはインスタンス化されない。

metaclass)とはクラスを定義しているクラスであるが、その実態はシステム側が用意している特別なシングルトンオブジェクトと考えた方が分かりやすい。システム内のクラス定義情報をクラスに見立てて、それをインスタンス化したものである。慣例的にこれをメタクラスと呼ぶ。メタクラスはクラスのデータメンバとメソッドの定義情報を指し、それを操作する機能はリフレクションと呼ばれる。クラスベースで用いられるものである。

reflection)はクラスの定義情報を変更する機能であるが、言語ごとに変更できる定義情報の範囲は異なっている。データメンバではデータ型、識別子、可視性が変更対象になる。メソッドではリターン型、識別子、パラメータリスト、可視性、仮想指定が変更対象になる。双方の追加定義と削除もできる事がある。スーパークラスも変更できる事がある。また、実行時の文字列(char配列やString)をデータメンバとメソッドの内部識別子として解釈できる機能もリフレクションに当たる。これは実行時の文字列によるデータメンバの参照とメソッドの呼び出しを可能にする。

遅延バインディング

late binding)は、識別子が参照するオブジェクトをコンパイル時に決める事前バインディング(early binding)の対義語であり、この場合は識別子の参照先を実行時に決める動的バインディングとほぼ同じ意味で用いられる。一方で、特にリフレクション機能を通して実装される方を遅延バインディングとする考え方もある。抽象化された型に対して、実行時の文字列(char配列やString)を内部識別子に解釈し、コンパイル時には認識されていなかったオブジェクトをローディングして代入する仕組みなどである。オブジェクトの呼び出しが、DLLやクラスライブラリの動的ローディングに繋がることが遅延バインディングと呼ばれる基準になる。ストアドプロシージャの動的ロード、代入、呼び出しもそれに当たる。ローディング基準が外される例では、プログラム内でデータとして扱われているコードブロックを関数の型に代入して呼び出すという仕組みがある。そのコードブロックは文字値と数値の混合配列であり、リフレクション機能を利用して実行する。

動的ディスパッチ

dynamic dispatch)はメソッドの呼び出しを受けるオブジェクトの側に焦点を当てたプログラム概念である。一般的なローカルメソッドでは、メソッド識別子にマッピングされている参照が指すメソッド実体を呼び出す仕組みを意味する。参照が指す先はプログラム実行中に随時変更されるのでコンパイル時ではなく実行時のその都度に確定されることになる。リモートメソッドでは、受け取ったバイトデータ列を解釈しリフレクション機能でメソッドを呼び出す仕組みを意味する。受信側の実行時状態による選択が加えられる事もある。始めのアクセスで所有メソッドリストを呼び出し側に送り、無駄なエラーリクエストを無くす仕組みと併用される事が多い。

dynamic binding)は特定の識別子から呼び出されるメソッドないし参照されるデータメンバが、コンパイル時ではなく実行時に決められる仕組み全般を指す用語である。プロトタイプベースのオブジェクトからメソッドとデータメンバが参照される機構、仮想関数メソッドから派生クラスのメソッドが呼び出されるシングルディスパッチ機構、メソッドに渡された実引数を実行時型チェックしてその結果に従いプロセスを分岐させるシングルディスパッチ~多重ディスパッチ機構などが例である。

脚注

関連項目