「メタクラス」の版間の差分
削除された内容 追加された内容
oldid=86393412 の記述は言語仕様からすると間違った記述が多いのに加えて、独自の意味を持たせた単語が多いため解釈が曖昧になるような表現が多いのですが検証しようにも出典がないので修正が難しくやむなく削除しました。 タグ: 2017年版ソースエディター |
タグ: 差し戻し済み ビジュアルエディター |
||
(同じ利用者による、間の4版が非表示) | |||
1行目:
'''メタクラス'''(Metaclass)は、[[オブジェクト指向
[[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]]では全てがオブジェクトである。また、Smalltalkはクラスベースであるため、オブジェクトは必ず、そのオブジェクトの構造(端的にはそのオブジェクトが有するインスタンス変数)や、そのオブジェクトがどんなメッセージを理解するのか(端的にはコールできるメソッド)を定義したいずれかのクラスに属さなければならない。このルールにおいてクラスも例外ではなく、Smalltalkではクラスもオブジェクトであり、同時に別のクラスのインスタンスでもある。このクラスのクラス、つまりあるクラスが属する特殊なクラスが「メタクラス」である。
76 ⟶ 80行目:
メタクラスはクラス生成時に同時に生成される。より具体的には、あるクラス(将来のスーパークラス)に対して、そのサブクラスとして例えば<code>Foo</code>を生成するように命ずると、まず暗黙のうちに<code>Foo class</code>が生成され、そのインスタンスとして<code>Foo</code>が生成される。先にも述べたがメタクラスは無名であり、クラスブラウザのクラス一覧にも現れえない。しかし、メタクラスが必ずクラスとペアで生成されることを利用して、クラスブラウザではclassボタン(古典的なクラスブラウザではクラス一覧を表示する枠に設置されている)を押して表示を切り替えることで対応するメタクラスの定義にアクセスしたりその内容(クラスインスタンス変数やクラスメソッド)を編集可能になっている。
=== Smalltalk-80のMOP ===
[[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は[[述語論理]]に準拠している。従ってそこでの[[継承 (プログラミング)|継承]]は[[必要条件]]と[[十分条件]]の関係で、[[インスタンス|インスタンス化]]は[[存在記号]]と[[全称記号]]の関係で考えると分かりやすくなる。
'''(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>はあらゆるユーザー定義クラスのメタクラスになる。そこまでの継承関係を下に示す。
# 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では、クラス自体が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]]
*
* [[Object Pascal]] (中でも[[Delphi]]が代表的である)▼
* [[Objective-C]]
* [[Ruby]]
* [[Python]]
* [[Perl]](メタクラスプラグマまたはMooseを用いて)
* [[
<!--
Please do not re-add the following languages to this list without discussing it on the talk page:
105 ⟶ 140行目:
-->
==関連項目==
*[[メタモデル]]
*[[メタデータ]]
*[[The Art of the Metaobject Protocol|メタオブジェクトプロトコル]]
*[[メタプログラミング]]
▲*[[リフレクション (情報工学)|リフレクション]]
*[[Adapter パターン]]
|