削除された内容 追加された内容
G000001 (会話 | 投稿記録)
oldid=86393412 の記述は言語仕様からすると間違った記述が多いのに加えて、独自の意味を持たせた単語が多いため解釈が曖昧になるような表現が多いのですが検証しようにも出典がないので修正が難しくやむなく削除しました。
タグ: 2017年版ソースエディター
Poshnegev (会話 | 投稿記録)
(同じ利用者による、間の4版が非表示)
1行目:
'''メタクラス'''(Metaclass)は、[[オブジェクト指向]][[プログラミング (コンピュータ)|プログラミング]]において'''メタクラス'''とはその[[インスタンス]]が[[クラス (コンピュータ)|クラス]]なるクラスを指す。つまりクラスのことクラスである。通常のクラスがそのイ[[オブジェクト (プログラミスタンスグ)|オブジェクト]]の振る舞いを定義すようのと同様に、メタクラスはそのインスタンスであるクラスの振る舞い定めて、そして更にれはのクラスのインスタンスの振る舞いを定義すにも反映される。全ての[[オブジェクト指向プログラミング]]言語メタクラスが利用できをサポートしていわけではない。利用できるものの中でもクラスの振る舞いが定義できる範囲は様々である。各言語はそれぞれ独自のメタオブジェクトプロトコル(MOP)備えている<ref>{{cite book|author=Ira R. Forman and Scott Danforth|title=Putting Metaclasses to Work|year=1999|isbn=0-201-43305-2}}</ref>。メタブジェクトプロトコルとは、クラスそのものの挙動をもオブジェクト指向のルルで記述し、初期化やインスタンス化のルル、実行状態の管理などをカスタマズする機構。[[Smalltalk]]という共通見解以外の特徴・性質・役割は[[Common Lisp]]([[CLOS]])が代表的言語別に様々である。
 
[[Smalltalk]]、[[Common Lisp]]([[CLOS]])、[[Ruby]]などでは、各{{仮リンク|メタオブジェクト|en|Metaobject}}の[[継承 (プログラミング)|継承]]と[[インスタンス|実体化]](後述)の連鎖で構成される末端物が、通常のプログラマが用いるクラスのメタクラスになっている。そのメタクラスは、クラスとその他メタ要素を[[第一級オブジェクト]]として扱えて組み立てられるオブジェクトである。メタオブジェクト・メタクラス・クラス・オブジェクトの相互関係・相互作用・相互組立の規則集は、[[The Art of the Metaobject Protocol|メタオブジェクトのプロトコル]](MOP)と呼ばれる<ref>{{cite book|author=Ira R. Forman and Scott Danforth|title=Putting Metaclasses to Work|year=1999|isbn=0-201-43305-2}}</ref>。
 
他の言語では、メタオブジェクトとそのプロトコルはシステム内封印されていることが多い。[[Python]]ではクラスの振る舞いを修正できる組み込みクラスがメタクラスと呼ばれている。[[Java]]や[[C Sharp|C#]]では[[アプリケーションプログラミングインタフェース|API]]の[[リフレクション (計算機科学)|リフレクション]]用インターフェースが事実上のメタクラスにされている。
 
==Pythonでの例==
58 ⟶ 62行目:
</syntaxhighlight>
 
==Smalltalkにおけるでのメタクラス==
[[File:Smalltalk 80 metaclassesSmalltalk_metaclass.svgpng|thumbリンク=https://en.wikipedia.org/wiki/File:Smalltalk_metaclass.png|サムネイル|Smalltalk-80でのメタクラスとクラスの継承関係を示すUML・実体化関係の]]
[[Smalltalk]]では全てがオブジェクトである。また、Smalltalkはクラスベースであるため、オブジェクトは必ず、そのオブジェクトの構造(端的にはそのオブジェクトが有するインスタンス変数)や、そのオブジェクトがどんなメッセージを理解するのか(端的にはコールできるメソッド)を定義したいずれかのクラスに属さなければならない。このルールにおいてクラスも例外ではなく、Smalltalkではクラスもオブジェクトであり、同時に別のクラスのインスタンスでもある。このクラスのクラス、つまりあるクラスが属する特殊なクラスが「メタクラス」である。
 
76 ⟶ 80行目:
メタクラスはクラス生成時に同時に生成される。より具体的には、あるクラス(将来のスーパークラス)に対して、そのサブクラスとして例えば<code>Foo</code>を生成するように命ずると、まず暗黙のうちに<code>Foo class</code>が生成され、そのインスタンスとして<code>Foo</code>が生成される。先にも述べたがメタクラスは無名であり、クラスブラウザのクラス一覧にも現れえない。しかし、メタクラスが必ずクラスとペアで生成されることを利用して、クラスブラウザではclassボタン(古典的なクラスブラウザではクラス一覧を表示する枠に設置されている)を押して表示を切り替えることで対応するメタクラスの定義にアクセスしたりその内容(クラスインスタンス変数やクラスメソッド)を編集可能になっている。
 
=== Smalltalk-80のMOP ===
クラスおよびメタクラスの振る舞いは次の4段階の継承階層を経て定義されている。
[[File:Smalltalk 80 metaclasses.svg|thumb|Smalltalk-80のMOPのUML図]]Smalltalkのメタオブジェクトプロトコルは(右図参照)'''(A)'''継承ルーツ(図左側の4×2ブロック)と、'''(B)'''インスタンス化ルーツの(図右側の縦5ライン)に分けて解釈できる。
 
'''(A)'''では、<code>Object class</code>が、<code>Object</code>の子孫クラス<code>Class</code>を継承して関係ループしている(上位型がその下位型の値を継承している)。これは[[ラムダ・キューブ|Lambda-P]]=[[依存型]]に相当し、即ちSmalltalkのMOPは[[述語論理]]に準拠している。従ってそこでの[[継承 (プログラミング)|継承]]は[[必要条件]]と[[十分条件]]の関係で、[[インスタンス|インスタンス化]]は[[存在記号]]と[[全称記号]]の関係で考えると分かりやすくなる。
:Object - インスタンス・クラスの別なく、オブジェクトとしての普遍的な振る舞い
::Behavior - クラスの最低限の振る舞い(コンパイルされたメソッドの保持やインスタンス生成)
:::ClassDescription (抽象クラス) - クラスの振る舞い(メソッドのコンパイルやカテゴリ管理)
::::Class - 通常のクラスの振る舞い(スーパークラスとしての振る舞いやクラス分類など)
::::Metaclass - メタクラス独自の振る舞い(一部メッセージをクラスにリダイレクトするなど)
 
'''(B)'''では、<code>Metaclass</code>と<code>Metaclass class</code>のインスタンス化関係がループしている。また、<code>Metaclass</code>は<code>Object</code>の子孫クラス<code>ClassDescription</code>を継承している。
== Rubyにおけるメタクラス ==
 
Rubyでは、クラス自体がClassというクラスのインスタンスであり、<code>Class.new</code>という形でクラスを動的に生成することもできる<ref>『[[#フラナガン&まつもと2009|プログラミング言語 Ruby]]』、p.278</ref>。ClassはModuleを継承しており、動的なメソッドの操作といったクラスに共通な機能があるほか、特異メソッド(あるオブジェクトだけに有効なメソッド)を使うことで、Smalltalk-76のような単一のメタクラスでクラスごとの多様性をもたせることができる。
<code>Object</code>はあらゆるユーザー定義クラスのスーパークラスになり、<code>Metaclass</code>はあらゆるユーザー定義クラスのメタクラスになる。そこまでの継承関係を下に示す。
具体的には、存在しないメソッドの呼び出しや、継承・メソッドの追加といったタイミングで呼び出されるフック関数を特異メソッドとして実装することができる<ref>『[[#フラナガン&まつもと2009|プログラミング言語 Ruby]]』、pp.287-290</ref>。
 
# Object - 全オブジェクト共通のデフォルト振る舞いの情報
# Behavior - コンパイル済みメソッドとオブジェクトの生成/実行の情報、オブジェクト分化の最低限
# ClassDescription - <code>Class</code>と<code>Metaclass</code>から見た抽象クラス。クラス変数の名前とコメントの情報
#* Class - <code>Object</code>の大元スーパークラス性質はここから
#* Metaclass - クラス変数の初期化、インスタンス生成メッセージの情報
 
== CLOSでのメタクラス ==
[[Common Lisp]] Object System([[CLOS]])の[[The Art of the Metaobject Protocol|メタオブジェクトプロトコル]](MOP)は、Smalltalkのをモチーフにしつつも数々の違いがある。SmalltalkのMOPが(上位型がその下位型の値を継承する)のループ関係を持つのに対して、CLOSのMOPは(上位型がその下位型のインスタンス化になる)のループ関係を持つ。これは[[ラムダ・キューブ|System Fω]]=型オペレータに相当し、即ちCLOSのMOPは高階の[[命題論理]]に準拠している。
 
CLOSのMOPの最上位クラス<code>T</code>は、その子孫クラス<code>built-in-class</code>を自身のメタクラスにしていて関係ループしている。<code>T</code>の子孫クラスの多くは<code>standard-class</code>をメタクラスにして関係ループしている。また、CLOSはメタオブジェクトを、<code>specializer</code>型特定子、<code>slot-definition</code>スロット定義、<code>generic-function</code>総称関数、<code>method</code>メソッド、<code>method-combination</code>メソッド結合、と明確に性格分けしている。
 
ここでは、ユーザー定義クラスのメタクラスである<code>standard-class</code>までの継承関係を下に示す。
 
# T - 全オブジェクトと全関数の大元
# standard-object - 全オブジェクトの大元スーパークラス
# metaobject - ここから<code>specializer</code>型特定子、スロット定義、総称関数、メソッド、メソッド結合に分化される。抽象クラス
# specializer - 型特定の情報。抽象クラス
# class - ここから<code>standard-class</code>標準クラス、組込クラス、関数クラス、転送クラスに分化される。抽象クラス
# standard-class - ユーザー定義クラスを定義できる
 
== Rubyにおけるでのメタクラス ==
Rubyでは、クラス自体がClassというクラスのインスタンスであり、<code>Class.new</code>という形でクラスを動的に生成することもできる<ref>『[[#フラナガン&まつもと2009|プログラミング言語 Ruby]]』、p.278</ref>。ClassはModuleを継承しており、動的なメソッドの操作といったクラスに共通な機能があるほか、特異メソッド(あるオブジェクトだけに有効なメソッド)を使うことで、Smalltalk-76のような単一のメタクラスでクラスごとの多様性をもたせることができる。具体的には、存在しないメソッドの呼び出しや、継承・メソッドの追加といったタイミングで呼び出されるフック関数を特異メソッドとして実装することができる<ref>『[[#フラナガン&まつもと2009|プログラミング言語 Ruby]]』、pp.287-290</ref>
[[ファイル:Ruby-metaclass-sample.svg|サムネイル|緑=継承関係、青=メタクラス関係、C=Class、A・B=クラス、u・v=オブジェクト]]
[[Ruby]]のMOPは、継承やインスタンス化のループ関係がない平易なものであり、<code>BasicObject</code>発のトップダウンの[[継承 (プログラミング)|継承]]ツリー構造になっている。だが、特異クラスの方はやや複雑になる。(右図参照)Rubyの特異クラス(eigenclassとも)は、[[Smalltalk]]のimplicitクラス(<code>Foo class</code>とか)を置き換えたものである。
 
まず、ユーザー定義クラスのメタクラスである<code>Class</code>までの継承関係を下に示す。
 
# BasicObject - 大元
#* Kernel - 全共通デフォルトメソッドを定義している。<code>Object</code>にインクルードされる
# Object - 全てのクラスのスーパークラス
# Module - モジュールのクラス。ユーザー定義モジュールを定義できる
# Class - クラスのクラス。ユーザー定義クラスを定義できる
RubyではクラスAをランタイム改装(メソッド追加など)すると、その特異クラスの方が改装されてそれがクラスAに反映されるようになっている。クラスAを定義すると<code>Class←Aの特異←A</code>のメタクラス関係ができるが、ここでAのサブクラスBを定義すると、<code>Class←Bの特異←B</code>のメタクラス関係もできて、<code>Aの特異←Bの特異</code>の継承関係もできる。
 
==利用可能な言語とツール==
有名な[[プログラミング言語]]でメタクラスが利用可能なものは以下である。
* [[Smalltalk]]
* [[Common Lisp]]([[Common Lisp Object System|CLOS]]を用いて)
* [[Groovy]]
* [[Object Pascal]] (中でも[[Delphi]]が代表的である)
* [[Objective-C]]
* [[Object Pascal]] (中でも[[Delphi]]が代表的である)
* [[Ruby]]
* [[Python]]
* [[Perl]](メタクラスプラグマまたはMooseを用いて)
* [[SmalltalkGroovy]]
<!--
Please do not re-add the following languages to this list without discussing it on the talk page:
105 ⟶ 140行目:
-->
 
次のようにそれほど普及していややマイナー言語の中にメタクラスが利用できるものある。いくつかは研究目的であり、1990年代初頭にまで遡る。例えば、[[OpenJava]]<ref>[http://csl.ensm-douai.fr/noury/uploads/1/nouryBouraqadi.Gpce03WorkshopOnRepls.pdf An implementation of mixins in Java using metaclasses]</ref>: [[OpenJava]]や[[OpenC++]]、[[OpenAda]]、[[CorbaScript]]、[[ObjVLisp]]、[[Object-Z]]、[[MODEL-K]]、[[XOTcl]]、[[MELDC]]などがある。[[Prolog]]のOOP拡張版[[Logtalk]]でもメタクラスが利用できる。また、[[Resource Description Framework]] (RDF)と[[Unified Modeling Language]] (UML)は両者共にメタクラスが利用できる
 
また、[[Prolog]]のオブジェクト指向拡張である[[Logtalk]]でもメタクラスが利用できる。
 
さらに、[[Resource Description Framework]] (RDF)と[[Unified Modeling Language]] (UML)は両者共にメタクラスが利用できる。
 
==関連項目==
*[[メタモデル]]
*[[メタデータ]]
*[[The Art of the Metaobject Protocol|メタオブジェクトプロトコル]]
*[[リフレクション (情報工計算機科学)|リフレクション]]
*[[メタプログラミング]]
*[[リフレクション (情報工学)|リフレクション]]
*[[Adapter パターン]]