「プロトタイプベース」の版間の差分
「行なう」→「行う」。 |
|||
(同じ利用者による、間の8版が非表示) | |||
1行目: | 1行目: | ||
{{出典の明記|date=2015年12月}} |
{{出典の明記|date=2015年12月}} |
||
[[ファイル:Smalltalk-metaclass-sample.svg|境界|右|フレームなし|248x248ピクセル]] |
|||
'''プロトタイプベース''' ({{lang-en-short|prototype-based}}) は、[[オブジェクト指向言語]]と総称される[[プログラミング言語]]のうち、[[プロトタイプ]]を基礎(ベース)として[[オブジェクト (プログラミング)|オブジェクト]]を取り扱うものをいう。'''[[インスタンス]]ベース'''とも。一方、[[クラス (コンピュータ)|クラス]]に基づいたオブジェクトインスタンスの生成を行う方式のものを[[クラスベース]]と呼ぶ。 |
|||
{{プログラミング・パラダイム}} |
|||
'''プロトタイプベース''' ({{lang-en-short|''prototype-based''}}) は、[[オブジェクト指向プログラミング]]のスタイルのひとつであり、{{仮リンク|メタオブジェクト|en|Metaobject|label=}}の仕組みを中心にした手法を指す。インスタンスベース(''instance-based'')とも呼ばれる。プロトタイプベースは1990年代前半から認知されるようになった後発のスタイルであり、先発の[[クラスベース]]のオブジェクト指向とは明確に区別されている。「[[Smalltalk]]」「[[Objective-C]]」「[[CLOS]]」「[[Self]]」「[[Oz (プログラミング言語)|Oz]]」「[[Lua]]」「[[Dylan]]」「[[Python]]」「[[JavaScript]]」「[[Ruby]]」「[[Io (プログラミング言語)|Io]]」「[[REBOL]]」「[[Julia (プログラミング言語)|Julia]]」といった[[スクリプト言語]]や[[Webプログラミング|Webプログラミング言語]]を中心に支持されている。 |
|||
メタオブジェクト(''metaobject'')は「[[LISP]]」由来のプログラム概念であり、実装的には[[変数 (プログラミング)|変数]]と[[関数 (プログラミング)|関数]]双方の[[識別子|識別名]]と[[参照 (情報工学)|参照値]]をペア定義できる可変サイズの[[構造体|データ構造体]]であることが多い。[[委譲]]先となる別のメタオブジェクトの識別名と参照値もペア定義できる。メタオブジェクトはフレーム&スロット(''frame&slot'')の機構名で読み替えられてもいる。プログラミング言語仕様上ではプロトタイプ(''prototype'')の機能名で実装されていることが多い。クラスの機能名で実装している言語もあるのでこの場合は誤解を招きやすくなっている。プロトタイプを複製して[[インスタンス]]が生成される。インスタンスはオブジェクトとも呼ばれる。プロトタイプは動的にカスタマイズできる「[[型システム|型]]」と見なせるものであり、その型を複製=量化したインスタンスは自由に加工/計算/代入できる「[[値 (情報工学)|値]]」になる。 |
|||
なおオブジェクト指向のスタイルとして、[[ビャーネ・ストロヴストルップ]]の[[C++]]流と、[[アラン・ケイ]]の[[Smalltalk]]流という分類がなされることもある。前者は由来となった[[Simula]]のクラスを強く受け継いだものであり、C++から派生した[[Java]]や[[C Sharp|C#]]などの大多数のオブジェクト指向言語にも受け継がれている。後者は[[アラン・ケイ]]の提唱した[[メッセージ (コンピュータ)|メッセージパッシング]]の概念に基づくものであり、[[Smalltalk]]の他にも、[[Objective-C]]や[[Ruby]]など、ある程度動的性を有し、かつ、コールしたメソッドが存在しない時にメソッドコール情報をメッセージとしてハンドリング可能とするフォールバック機構を有する言語にその精神が受け継がれている。 |
|||
<!--<ref>http://d.hatena.ne.jp/sumim/20040525/p1 を参照</ref>--> |
|||
<!-- 信頼性が担保されない個人のブログ記事は、単体では有効な出典になりえない。[[Wikipedia:信頼できる情報源]] --> |
|||
== 特徴 == |
== 特徴 == |
||
クラス = 構造化されたデータ + それに所属するメソッド、という考え方はプログラムの整理に劇的な威力を発揮する。しかし、全てがクラスベースであるという前提は時に物事を複雑化してしまう。 |
|||
=== メタオブジェクト === |
|||
問題となるのはクラスが静的な構造と結びついているという点である。 |
|||
{{Quotation|あなたはプロトタイプを作り、新しいインスタンスを作る。双方のオブジェクトは変幻自在だ。新しいフィールドとメソッドを付け足して拡充できる。その行為はプロトタイプと同等である。類似オブジェクトを作るためのクラスとその継承も必要ない。これ以上のオブジェクト指向があるだろうか?|Douglas Crockford(JavaScript developer)}}標準的なメタオブジェクトは「フレーム&スロット」「シンボル」「データ」「コード」の四要素から構成される。この四要素はいずれもオブジェクトである。データは変数値/定数値を指す。コードは引数有り/無し関数式を指す。シンボルはいわゆる識別子であり、データが束縛されたら変数名になり、またコードが束縛されたら関数名になる。フレーム&スロットはシンボル(変数名/関数名)が集約される媒体であり、プロトタイプ/インスタンスを指す。プロトタイプは所有シンボル先の要self変数に値を代入できず、また所有シンボル先の要self関数を呼び出せないオブジェクトである。インスタンスはそれらが可能なオブジェクトである。要self変数/関数はインスタンス変数/関数であり、そうでないものはクラス変数/関数である。インスタンスはプロトタイプを複製する方式で生成される。プロトタイプとインスタンスは共にそのメンバとなる変数と関数を自由に付け足すことができる。上述のメカニズムから変数と関数もオブジェクト(フレーム&スロット)になるので、変数にそのメンバ変数/メンバ関数を持たせることも可能であり、関数ではそのローカル変数/ローカル関数が、メンバ変数/メンバ関数として解釈される。シンボルはオブジェクトを識別するための用途にほぼ限られているが、仕組み上はそれにもメンバを付けることができる。シンボルは上述の四要素とプロトタイプ/インスタンスを分類するためのメタ情報IDとしても使われる。また後述のセレクタ(振る舞い指示子)としても使われる。 |
|||
フレーム&スロット、変数値、関数式、関数の引数値、関数の返り値は、それぞれがお互いをメンバにできるので、入れ子の連結関係で所有ないし所属し合えるようになっている。変数値にメンバ変数/メンバ関数を付けると、[[クラスベース]][[オブジェクト指向プログラミング|OOP]]の[[インスタンス]]と同等になる。void関数は専用の書式でクラスベースOOPのインスタンスと同等になり、そのvoid関数内のローカル変数/ローカル関数がメンバ変数/メンバ関数になる。メンバ変数付き関数とメンバ関数付き変数は、[[関数オブジェクト]]または[[クロージャ]]と同等なものである。 |
|||
例えばメソッドが必ず何らかのクラスに所属するという前提は強すぎる場合がある。クラスベースでは[[委譲]]や代理(プロキシ)によって動作にバリエーションを与えるが、初めからバリエーションをもったインスタンスを作成できればそのような機構は必要ない。 |
|||
=== デリゲーション === |
|||
またインスタンス変数とメソッドの違いとは何か、という問題もある。[[C++]]や[[Java]]のpublicなメンバ変数([[フィールド (計算機科学)|フィールド]])などを別にすれば、インスタンス変数とアクセサメソッドはほとんど等価の概念である。 |
|||
オブジェクトのメンバ関係の連鎖メカニズムは、デリゲーション([[委譲]])によるオブジェクトのコミュニケーションを活性化させる。これにはセレクタ(振る舞い指示子)を用いる言語もあるが、大抵はコールするその関数オブジェクト名またはそのメソッド名が振る舞い指示子と同義になっている。関数オブジェクトが引数とともにコールされてそこで指定処理に対応できない場合は、そのメンバ関数またはメンバ変数のメッセージレシーバーに引数を渡してそちらに委譲する。委譲先でも不可だった場合はそのまた次のメンバにたらい回しもできる。オブジェクトはそのたらい回しの結果返ってきた値を自身の返り値にできる。 |
|||
=== ダックタイピング === |
|||
そこでプロトタイプベースでは、全てのオブジェクトをスロットなどと呼ばれる、アクセス名と結びついた汎用の変数領域の塊でできた可変構造体として捉え直し、そこに他のオブジェクトへの参照やメソッドなどを自由に定義できるようにする。つまりオブジェクトは参照とメソッドの集積体であり、いかなる静的構造とも結びつかない。 |
|||
=== カプセル化/継承/多態性 === |
|||
クラスが存在しない世界ではテンプレート処理によるインスタンス化ができないため、新しいオブジェクトは完全に空の状態か、または他のオブジェクトの複製(クローン)によって作成される。プロトタイプベースでの継承は一般にこのクローンによる特性の引き継ぎを指す。 |
|||
=== 関数型的側面 === |
|||
=== 総論 === |
|||
メタオブジェクトを基礎にしたプロトタイプベースは、さながら原生動物のようなプログラミングパラダイムであり、手続き型、関数型、クラスベースOOPといった様々な形態で取り扱うことができる。 |
|||
== 来歴 == |
|||
== 脚注 == |
== 脚注 == |
||
25行目: | 31行目: | ||
== 関連項目 == |
== 関連項目 == |
||
⚫ | |||
*[[Lua]] |
|||
*[[Perl]] |
|||
*[[REBOL]] |
|||
*[[Self]] |
*[[Self]] |
||
*[[Smalltalk]] |
|||
⚫ | |||
{{プログラミング言語の関連項目}} |
{{プログラミング言語の関連項目}} |
||
35行目: | 39行目: | ||
{{DEFAULTSORT:ふろとたいふへえす}} |
{{DEFAULTSORT:ふろとたいふへえす}} |
||
[[Category:オブジェクト指向]] |
[[Category:オブジェクト指向]] |
||
[[Category:型理論]] |
|||
{{Computer-stub}} |
{{Computer-stub}} |
2021年1月18日 (月) 10:42時点における版
プログラミング・パラダイム |
---|
プロトタイプベース (英: prototype-based) は、オブジェクト指向プログラミングのスタイルのひとつであり、メタオブジェクトの仕組みを中心にした手法を指す。インスタンスベース(instance-based)とも呼ばれる。プロトタイプベースは1990年代前半から認知されるようになった後発のスタイルであり、先発のクラスベースのオブジェクト指向とは明確に区別されている。「Smalltalk」「Objective-C」「CLOS」「Self」「Oz」「Lua」「Dylan」「Python」「JavaScript」「Ruby」「Io」「REBOL」「Julia」といったスクリプト言語やWebプログラミング言語を中心に支持されている。
メタオブジェクト(metaobject)は「LISP」由来のプログラム概念であり、実装的には変数と関数双方の識別名と参照値をペア定義できる可変サイズのデータ構造体であることが多い。委譲先となる別のメタオブジェクトの識別名と参照値もペア定義できる。メタオブジェクトはフレーム&スロット(frame&slot)の機構名で読み替えられてもいる。プログラミング言語仕様上ではプロトタイプ(prototype)の機能名で実装されていることが多い。クラスの機能名で実装している言語もあるのでこの場合は誤解を招きやすくなっている。プロトタイプを複製してインスタンスが生成される。インスタンスはオブジェクトとも呼ばれる。プロトタイプは動的にカスタマイズできる「型」と見なせるものであり、その型を複製=量化したインスタンスは自由に加工/計算/代入できる「値」になる。
特徴
メタオブジェクト
あなたはプロトタイプを作り、新しいインスタンスを作る。双方のオブジェクトは変幻自在だ。新しいフィールドとメソッドを付け足して拡充できる。その行為はプロトタイプと同等である。類似オブジェクトを作るためのクラスとその継承も必要ない。これ以上のオブジェクト指向があるだろうか? — Douglas Crockford(JavaScript developer)
標準的なメタオブジェクトは「フレーム&スロット」「シンボル」「データ」「コード」の四要素から構成される。この四要素はいずれもオブジェクトである。データは変数値/定数値を指す。コードは引数有り/無し関数式を指す。シンボルはいわゆる識別子であり、データが束縛されたら変数名になり、またコードが束縛されたら関数名になる。フレーム&スロットはシンボル(変数名/関数名)が集約される媒体であり、プロトタイプ/インスタンスを指す。プロトタイプは所有シンボル先の要self変数に値を代入できず、また所有シンボル先の要self関数を呼び出せないオブジェクトである。インスタンスはそれらが可能なオブジェクトである。要self変数/関数はインスタンス変数/関数であり、そうでないものはクラス変数/関数である。インスタンスはプロトタイプを複製する方式で生成される。プロトタイプとインスタンスは共にそのメンバとなる変数と関数を自由に付け足すことができる。上述のメカニズムから変数と関数もオブジェクト(フレーム&スロット)になるので、変数にそのメンバ変数/メンバ関数を持たせることも可能であり、関数ではそのローカル変数/ローカル関数が、メンバ変数/メンバ関数として解釈される。シンボルはオブジェクトを識別するための用途にほぼ限られているが、仕組み上はそれにもメンバを付けることができる。シンボルは上述の四要素とプロトタイプ/インスタンスを分類するためのメタ情報IDとしても使われる。また後述のセレクタ(振る舞い指示子)としても使われる。
フレーム&スロット、変数値、関数式、関数の引数値、関数の返り値は、それぞれがお互いをメンバにできるので、入れ子の連結関係で所有ないし所属し合えるようになっている。変数値にメンバ変数/メンバ関数を付けると、クラスベースOOPのインスタンスと同等になる。void関数は専用の書式でクラスベースOOPのインスタンスと同等になり、そのvoid関数内のローカル変数/ローカル関数がメンバ変数/メンバ関数になる。メンバ変数付き関数とメンバ関数付き変数は、関数オブジェクトまたはクロージャと同等なものである。
デリゲーション
オブジェクトのメンバ関係の連鎖メカニズムは、デリゲーション(委譲)によるオブジェクトのコミュニケーションを活性化させる。これにはセレクタ(振る舞い指示子)を用いる言語もあるが、大抵はコールするその関数オブジェクト名またはそのメソッド名が振る舞い指示子と同義になっている。関数オブジェクトが引数とともにコールされてそこで指定処理に対応できない場合は、そのメンバ関数またはメンバ変数のメッセージレシーバーに引数を渡してそちらに委譲する。委譲先でも不可だった場合はそのまた次のメンバにたらい回しもできる。オブジェクトはそのたらい回しの結果返ってきた値を自身の返り値にできる。
ダックタイピング
カプセル化/継承/多態性
関数型的側面
総論
メタオブジェクトを基礎にしたプロトタイプベースは、さながら原生動物のようなプログラミングパラダイムであり、手続き型、関数型、クラスベースOOPといった様々な形態で取り扱うことができる。