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

削除された内容 追加された内容
m ミックスイン: つもりやもり氏の独自研究と思われる部分を整理
m 用語と解説: 独自研究色の強い箇所をコメントとしました。随時出典を明記しコメントを外してください。
118行目:
:(''class'')の仕組みを中心にしたオブジェクト指向を[[クラスベース]]と言う。クラスはデータとメソッドをまとめたものであり、[[プログラム意味論|操作的意味論]]を付加された静的[[構造体|レコード]]とも解釈される。クラスはインスタンスのひな型であり、インスタンスはクラスを実例化(量化)したものである。クラスはカプセル化、継承、多態性の三機能を備えていることが求められている。カプセル化は[[This (プログラミング)|this参照]]の仕組みの実装およびデータとメソッドの可視性を指定できる機能である。継承は自身のスーパークラスを指定できる機能である。多態性は[[オーバーライド]]と[[仮想関数テーブル]]を処理する機能である。コンストラクタとデストラクタの実装も必要とされている。前者はインスタンス生成時に、後者はインスタンス破棄時に呼び出されるメソッドである。
;プロトタイプ
:(''prototype'')の仕組みを中心にしたオブジェクト指向を[[プロトタイプベース]]と言う。<!--プロトタイプとは識別名&中間参照ペアの集合体を指す。この集合体は一般にフレームと呼ばれる。識別名&中間参照ペアの割り当て箇所は一般にスロットと呼ばれる。スロットにはデータとメソッドの識別名&中間参照ペアが代入されるので、プロトタイプはクラスと同様にデータとメソッドをまとめたものになる。プロトタイプは言語によってはクラスと呼ばれている。プログラマはシステムが提供する基底プロトタイプに、自由にデータとメソッドを付け足して任意の派生プロトタイプを作成できる。プロトタイプは「型」相当であり、それを複製する方式で生成されるインスタンスは「値」相当である。データとメソッドはその参照にインスタンスを必要とするものと、しないものに分かれる。前者はインスタンスメンバ、後者は静的メンバに相当するものである。インスタンスにも自由にデータとメソッドを付け足すことができる。インスタンスはそのプロトタイプへの参照を保持しており、プロトタイプはその親プロトタイプへの参照を保持している。これは継承相当の機能になっている。インスタンスへの自由なメンバ付け替えは多態性相当の機能になっている。ただしプロトタイプは動的な[[関数型言語]]由来の仕様なのでクラスベースOOPの三大要素とはまた違った視点から眺める必要がある。--><!-- 独自研究に思えます。出典がないので検証ができません -->
;[[メッセージ (コンピュータ)|メッセージ]]
:オブジェクト指向で言われるメッセージ(''message'')とは、オブジェクトの呼び出し側と呼び出される側の間であらゆる事柄が実行時に決められる仕組み全般を指す用語である。関数名の解釈、引数構成、返り値構成、関数名対応プロセス所有の是非、委譲先、同期/非同期タイミングといったものが実行時のその都度に決められる。実行時に解釈される関数名文字列はセレクタと呼ばれる。これは無制限に柔軟な仕様の関数呼び出しと考えてもよいものであり、その実装方式の明確な定義はない。代表例を挙げると分散オブジェクトや分散システムで用いられているメッセージパッシングは、関数名も実行時に解釈できる引数要素にした仕組みである。Smalltalk指向の言語に導入されているメッセージレシーバーとメソッドミッシングでは、特定のセレクタに対応するプロセスをコンパイル時定義できるようにして自動実行時選択されるようになっており、プロセス未定義セレクタだけが実行時解釈される仕組みになっている。このコンパイル時定義のセレクタプロセスをメソッドと呼んだ。OOPでメンバ関数をわざわざメソッドと呼ぶのはメッセージパッシング由来のこうした経緯からである。アラン・ケイはメッセージング(''messaging'')というより遠大な構想を持っていた。
131行目:
;[[デストラクタ]]
:(''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'')は、同じメソッド名(返り値の型+メソッド名)にそれぞれ異なるパラメータリスト(引数欄)を付けたものを列挙してメソッドを多重定義する仕組みを指す。[[演算子]]もオーバーロード対象であり、[[単項演算子]]なら一つの引数の型、[[二項演算子]]なら二つの引数の型を多重定義することで演算対象の値の型ごとに計算内容をカスタマイズできる。任意個数の引数を多重定義できる( )演算子は、[[クロージャ]]または[[関数オブジェクト]]の表現に用いられる。
 
;[[オーバーライド]]
:(''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'')は、メソッドシグネチャ(返り値の型+メソッド名+各引数の型と個数)だけが定義されてコード内容が省略されているメソッドである。抽象クラスはインスタンス化できないので継承専用になる。抽象メソッドはそのサブクラスの方でコード内容が実装されてオーバーライドされる。
<!--
 
{{型システム}}
;[[インタフェース (抽象型)|インターフェース]]
:(''interface'')はプログラム概念と機能名の双方を指す用語である。インターフェースは、抽象メソッドのみで構成される純粋抽象クラスを指しているが、言語によっては実体メソッドのメンバも許されている事がある。データはメンバにされないが、定数は許されている事がある。インターフェースはクラスの振る舞い側面を抜き出した抽象オブジェクトと解釈されている。クラスはインターフェースを実装継承し、多重継承可能である。インターフェースは自身を実装継承した[[下位概念]]クラスをグループ化できる。インターフェースは{{仮リンク|記名的型付け|en|Nominal type system|label=}}に準拠しているので実装されたインターフェース名の明記が自身の[[下位概念]]の判別基準にされる。抽象クラスと同様にインスタンス化はできない。言語によってはプロトコルとも呼ばれ、この場合は記名ではなくメンバ構成が自身の[[下位概念]]の判別基準になる{{仮リンク|構造的型付け|en|Structural type system|label=}}の性質を備えたものにされている。
--><!-- 記述の必要性が薄いように思えます(言語固有) -->
;[[ミックスイン]]
:多重継承を扱う際の作法の一つである。作法の発祥地である[[:en:Flavors|Flavors]]やそれを継承した[[Common Lisp]]のように、プログラミング上で励行される単なる作法である場合と、[[Ruby]]のように言語機能へ組み込まれた<ref>{{cite web |url=https://docs.ruby-lang.org/ja/latest/doc/spec=2fintro.html |title=Ruby 3.0.0 リファレンスマニュアル: モジュールによるMix-in | accessdate=2021-03-01}}</ref>場合がある。
<!--
;型イントロスペクション
:''(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'')は、クラスのデータ、メソッド、スーパークラス、内部クラスなどの定義情報を記録した[[メタデータ]]である。<!-- クラスベースのメタクラス機能は、実装レベルではシステム側が用意している特別なシングルトンオブジェクトと考えた方が分かりやすい。それにはシステム側が提供するインターフェースを通してのみアクセスできる。メタクラス内容を閲覧/変更できる機能はリフレクションと呼ばれる。プロトタイプベースでは、インスタンスの複製元であるプロトタイプ/クラス自体がメタクラス機能を備えており、データとメソッドを動的に付け替えできる。--><!-- 独自研究に思えます。出典がないので検証ができません -->
;[[リフレクション (情報工学)|リフレクション]]
:(''reflection'')は、メタクラス内容を閲覧/変更する機能であるが、変更できる内容範囲は言語ごとに異なっている。データではデータ型、識別子、可視性が変更対象になる。メソッドではリターン型、識別子、パラメータリスト、可視性、オーバーライド指定が変更対象になる。双方の追加定義と削除もできる事がある。スーパークラスも変更できる事がある。メタクラスの変更はそのまま関連クラスと関連インスタンスに反映される。ただし反映範囲はこれも言語によって異なる。
:また、実行時の文字列(char配列やString)をデータとメソッドの内部識別子として解釈できる機能もリフレクションであり、上述のメタクラス操作よりもこちらの方がよく用いられる。これは実行時の文字列データを用いてのデータ/メソッドへの動的なアクセスを可能にする。
<!--
;[[アノテーション|メタアノテーション]]
:(''metadata annotation'')はクラスに任意の情報を埋め込める機能である。情報とは文字列と数値からなるキーワード、シンボル、テキストである。プログラマが自由な形式で書き込んで随時読み取るものであるが、システムから認識される形式のものもある。実装レベルではメタクラスに書き込まれてリフレクション機能またはその[[糖衣構文]]で読み取ることになる。[[マーカーインタフェース|マーカーインターフェース]]の拡張とも見なされている。メタアノテーションはクラス単位だけでなく、言語によってはインスタンス単位やメソッド単位でも埋め込むことができる。
;メソッド拡張
:(''method extension'')は、クラス定義とは別の場所でそのクラスに対する追加メソッドを定義できる機能である。これは状況に合わせてデータ抽象の表現に幅を持たせることを目的にしている。これには数々の書式があるが代表的なのは、静的メソッドまたは静的関数の第1引数をthis修飾して、その第1引数のクラス(型)に対してその静的メソッドをインスタンスメソッドとして追加するというものである。静的メソッドはそのクラススコープ内の限定拡張にできる。静的関数はネスト関数にしてそのローカルスコープ内の限定拡張にできる。双方はグローバル用途にすることもできる。
--><!-- 記述の必要性が薄いように思えます(言語固有) -->
 
<!--
;動的ディスパッチ
:(''dynamic dispatch'')は、コンパイル時のメソッド名から呼び出されるメソッド内容が実行時に決定される仕組み全般を指す用語である。メソッドに引数を渡しての呼び出しを、オブジェクトにメッセージを発送(ディスパッチ)することになぞらえた事が由来である。発送先は実行時に選択決定されるメソッド内容を指す。メッセージは「[[This (プログラミング)|this参照]]×第1引数×第2引数..」といった[[直積集合]]で考えられているのでシングル、ダブル、マルチプルといった呼称になっている。発送先はthisおよび各引数の派生関係の組み合わせで選択される。thisの派生関係のみ影響しているものは仮想関数と呼ばれるシングルディスパッチになる。それがthisでなく引数ならばただのシングルディスパッチになる。thisまたは各引数の内の2個以上のオブジェクトの派生関係が影響しているものは[[多重ディスパッチ|マルチプルディスパッチ]]になる。その中で特にthisと先頭引数の2個が影響して先頭引数インスタンスの仮想関数がthisを引数にしているVisitor形態のものは[[ダブルディスパッチ]]と呼ばれている。
;[[動的束縛|動的バインディング]]
:(''dynamic binding'')は、識別子が参照するまたは呼び出すオブジェクト、インスタンス、メソッド、データなどのプログラム要素が、コンパイル時ではなく実行時に決められる仕組み全般を指す用語である。識別子はいわゆる変数名や関数名などを指す。
--><!-- 記述の必要性が薄いように思えます(言語固有) -->
 
<!--
;遅延バインディング
:(''late binding'')は、識別子が参照するオブジェクトをコンパイル時に決める事前バインディング(''early binding'')の対義語であり、この場合は識別子が参照するオブジェクトを実行時に決める動的バインディングと同じ意味で用いられる。また他方では動的バインディングの中で、特に実行コードの動的ローディング機能を通して実装される方を遅延バインディングとする考え方もある。実行コードとは[[ダイナミックリンクライブラリ|DLL]]やクラスライブラリやモジュールなどを指しており、それらが内包するクラスやメソッドを専用の不透明型または動的束縛型に代入する。その呼び出しのための内部識別子はコンパイル時には存在していないことが多いので、実行時の文字列(char配列やString)を内部識別子に解釈するためのリフレクション機能が多用されることになる。
--><!-- 記述の必要性が薄いように思えます(言語固有) -->
 
<!--
;[[パッケージ (Java)|パッケージ]]
:(''package'')は1個以上のクラスをまとめたものである。多くなったクラスをグループ化するための仕組みである。パッケージの定義は言語ごとに異なるが、[[名前空間]](''namespace'')と同等の機能になっているケースが多い。実装レベルではパッケージ名は自動的にクラス名の接頭辞になってクラス名を差別化し、名前衝突を回避している。
--><!-- 記述の必要性が薄いように思えます(言語固有) -->
 
<!--
;[[モジュール]]
:(''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''と呼ばれる。
--><!-- 記述の必要性が薄いように思えます -->
 
;[[委譲|デリゲーション]]
:委譲(''delegation'')。呼び出されたあるクラスのメソッドが自分への引数を他のクラスの同名メソッドにそのまま渡して、その同名メソッドからの返り値をそのまま呼び出し元に渡すという仕組みを指す。委譲先のクラスはhas-a関係で保有されているものになる。委譲先メソッドは必ずしも同名ではなくマッピング名の場合もあり、引数も構成を変えて渡される場合もある。
<!--
;フォワーディング
:転送(''forwarding'')。委譲先のクラスのメソッドが処理を行わずに、そのまた他のクラスの同名メソッドに引数をそのまま渡して、その返り値をそのまま呼び出し元に渡している場合、冒頭の委譲は転送になる。転送用メソッドではどのクラスに引数をパスするかという選択が行われるので、デリゲーションの多相を表現できる。
--><!-- 記述の必要性が薄いように思えます -->
 
;[[派生型|サブタイピング]]
:(''subtyping'')はクラス(型)のあらゆる派生関係および派生構造の実装形式とその働き方を包括したプログラム概念である。サブタイプ多相(''subtype polymorphism'')とも呼ばれる。継承、オーバーライド、コンポジション、ジェネリクス、共変反変バリアンス、不透明型といったものは全てサブタイピングの一側面である。オブジェクト指向でよく使われるものは、振る舞いサブタイピング(''behavioral subtyping'')であり、継承とメソッドオーバーライドの合わせ技である仮想関数がそれに当たる。
232 ⟶ 265行目:
:* (I){{仮リンク|インターフェース分離原則|en|Interface segregation principle|label=}}は、一つのクラスから実現される抽象クラスを一つに限定せず、互いに処理内容に影響し合うメソッド群ごとに分離して複数実現することを推奨している。
:* (D)[[依存性逆転の原則|依存性逆転原則]]は、AクラスがBクラスの機能を使用したい場合は、まずBからその抽象クラスをAに向けて実現し、Aはその抽象クラスを通してBの機能を使用することを推奨している。AはBの機能を使用するという意味でその抽象クラスに依存し、Bは自身の機能を提供するという意味でその抽象クラスに依存することになる。ここでの逆転(''inversion'')とは実装から抽象への方向性を意味している。
<!--
 
; [[デザインパターン (ソフトウェア)|GOFデザインパターン]]
: (''Gang of Four Design Patterns'')はソフトウェア開発において直面しやすい共通的かつ代表的なデザイン問題をピックアップし、それぞれの解決に最適なクラスパターン図を提示したものである。1994年から四人の計算機科学者ないしソフトウェア技術者たち([[Gang of Four]])によって発表され、OOPのデザインパターンの代表格と見なされた。教科書の内容としても取り上げやすい形式化されたトピックであったためにオブジェクト指向の学習面では非常に重視された。5個の生成パターン、7個の構造パターン、11個の振る舞いパターンに分類されている。
264 ⟶ 297行目:
ファイル:Visitor UML class diagram.svg|[[Visitor パターン|Visitor]]
</gallery>
-->
<!-- ↑独立したページが存在するため関連項目へのリンクとするのが簡潔ではないでしょうか -->
 
== 脚注 ==