Smalltalkでのメタクラス
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/12/06 12:23 UTC 版)
「メタクラス」の記事における「Smalltalkでのメタクラス」の解説
Smalltalkでは全てがオブジェクトである。また、Smalltalkはクラスベースであるため、オブジェクトは必ず、そのオブジェクトの構造(端的にはそのオブジェクトが有するインスタンス変数)や、そのオブジェクトがどんなメッセージを理解するのか(端的にはコールできるメソッド)を定義したいずれかのクラスに属さなければならない。このルールにおいてクラスも例外ではなく、Smalltalkではクラスもオブジェクトであり、同時に別のクラスのインスタンスでもある。このクラスのクラス、つまりあるクラスが属する特殊なクラスが「メタクラス」である。 例えば、「自動車」クラスCarから生成されたオブジェクトaCarが、Carのインスタンスであり、Carというクラスに属しているのと同じように、クラスCar自身にも自らが属しているクラス、つまりメタクラスが存在する。原則としてSmalltalkでメタクラスは無名扱いだが、便宜的にクラス名にclassを付して呼称する慣習がある。Carなら、そのメタクラスはCar classである。なおこの表記は(クラスに限らず)あるオブジェクトが属するクラスを第一級オブジェクトとして得るためのSmalltalk式としての意味も併せ持つ(aCar class "=> Car ". (aCar class) class "=> Car class ")。 クラスメソッド(クラスがコールできるメソッド)は、通常、メタクラスに定義されている。これはインスタンスメソッドがクラスに定義されているのと考え方は同じである。 インスタンスメソッドの場合、たとえば整数の「2」というオブジェクトに何らかのメッセージを送ると、2が属するSmallIntegerというクラスから対応するメソッドがないか探し始める。SmallIntegerに見つからなければそのスーパークラスであるIntegerで…というようにスーパークラスを次々と手繰ってゆき、最後のObjectというルートクラスまで探索を続ける。 クラスメソッドの場合も考え方はほとんど変わらない。たとえばSmallIntegerというクラスに対してメッセージを送ると、メソッド検索はそのクラスであるSmallInteger classから開始される。そしてインスタンスメソッドの場合と同様に、SmallInteger classのスーパークラスであるInteger class、さらにそのスーパークラスを次々と手繰り、Object class(Objectクラスのメタクラス)まで探索を続ける。なおSmalltalkにおいては、メタクラスの継承関係は原則としてそのインスタンスであるクラスの継承関係と一致する。つまりSmallIntegerのスーパークラスがIntegerなら、そのメタクラス同士も同じ関係、すなわち、SmallInteger classのスーパークラスはInteger classである。ただしObject classだけは例外で、Objectのスーパークラスが未定義(nil)であるのに対し、Object classのスーパークラスはClassと定められている。したがって、クラスへのメッセージ送信に伴うメソッド探索はObject classでは終了せず、クラスとしての振る舞いを定めたClassとそのスーパークラスパスにある二つのクラス(ClassDescriptionとBehavior。後述)を経てObjectに行き着くまで続行される。同時にこのことはSmalltalkにおいてクラスもオブジェクトである、すなわちクラスObjectの(サブ)インスタンスであり、通常のクラスのインスタンス同様Objectに定義されたメソッドをコールできることの理由をうまく説明している。 初期のSmalltalk(Smalltalk-76)には、同じくClassと名付けられたたったひとつのメタクラスしか用意されていなかった。つまりこのことは、すべてのクラスはClassのインスタンスであり、他のクラスと同じ共通のメソッドしか持つことができなかった(たとえば、新しいインスタンスを作るためのnewというメソッドなど)ということを意味する。その後、クラスが独自のメソッド(クラスメソッド)やインスタンス変数(クラスインスタンス変数と呼ばれる。クラスとそのインスタンスで共有できるクラス変数と混同されやすいが別物である)を持てるように、Smalltalk-80では改めてクラスそれぞれが固有のメタクラスが生成されるように拡張され今のかたちになった。 クラスのクラスであるメタクラスは、インスタンスのクラスである通常のクラスほどには独自性を要求されないので、すべてのメタクラスはMetaclassという名のひとつクラスのインスタンスとして位置づけられている。ちなみにMetaclassのメタクラスはMetaclass classだが、同時にこれは前述のルールに則りMetaclassのインスタンスでもある。このトリックによって、さらにメタ、さらにそのメタ…と永遠に繰り返さずにも済むようになっている。 メタクラスはクラス生成時に同時に生成される。より具体的には、あるクラス(将来のスーパークラス)に対して、そのサブクラスとして例えばFooを生成するように命ずると、まず暗黙のうちにFoo classが生成され、そのインスタンスとしてFooが生成される。先にも述べたがメタクラスは無名であり、クラスブラウザのクラス一覧にも現れえない。しかし、メタクラスが必ずクラスとペアで生成されることを利用して、クラスブラウザではclassボタン(古典的なクラスブラウザではクラス一覧を表示する枠に設置されている)を押して表示を切り替えることで対応するメタクラスの定義にアクセスしたりその内容(クラスインスタンス変数やクラスメソッド)を編集可能になっている。
※この「Smalltalkでのメタクラス」の解説は、「メタクラス」の解説の一部です。
「Smalltalkでのメタクラス」を含む「メタクラス」の記事については、「メタクラス」の概要を参照ください。
- Smalltalkでのメタクラスのページへのリンク