メタクラス

オブジェクト指向プログラミングにおいて**メタクラス**とは、インスタンスがクラスとなるクラスのことである。通常のクラスがそのインスタンスの振る舞いを定義するように、メタクラスはそのインスタンスであるクラスを、そして更にそのクラスのインスタンスの振る舞いを定義する。全てのオブジェクト指向プログラミング言語でメタクラスが利用できるわけではない。利用できるものの中でもクラスの振る舞いが定義できる範囲は様々である。各言語はそれぞれメタオブジェクトを操作する手続きがあり、言語仕様によりプロトコル化(構造化されたインターフェース)されている場合は特にメタオブジェクトプロトコル(MOP)と呼ばれる。メタオブジェクトプロトコルとは、クラスそのものがオブジェクトで表現されており(メタオブジェクト)、オブジェクト指向のルールで、これらの初期化やインスタンス化のルール、実行状態の管理などをカスタマイズする機構である。Smalltalk、Common Lispが代表的である。

## Pythonでの例
Pythonの組み込み(ビルトイン)クラス `type` はメタクラスである。次に示す単純なPythonのクラスについて説明する。


```python
class Car(object):
    __slots__ = ['make', 'model', 'year', 'color']

    def __init__(self, make, model, year, color):
        self.make = make
        self.model = model
        self.year = year
        self.color = color

    @property 
    def description(self):
        """ このCarの説明を返す """
        return "%s %s %s %s" % (self.color, self.year, self.make, self.model)
```


このコードを実行した時、`Car` は `type` のインスタンスになっている。上記の `Car` クラスのソースコードには `__init__` メソッドが `Car` のインスタンスが生成されるたびに呼ばれるといった細々としたことは記述されていない。メタクラスが用意されていない言語ではこのような振る舞いは言語仕様で定義されており、変更することは不可能である。Pythonではメタクラス `type` がこれらの動作を決定しており、`type` の代わりに違うメタクラスを使用することでこれらの振る舞いを変更することが可能である。

上に示した例は4つの属性 `make` と `model`、`year`、`color` の辺りが冗長である。メタクラスを使えば、この冗長さを取り除くことが可能である。Pythonではメタクラスは `type` のサブクラスとして定義するのが最も簡単である。

```python
class AttributeInitType(type):
     def __call__(self, *args, **kwargs):
         """ 新しいインスタンスを生成する """
 
         # 普通にインスタンスを生成する
         obj = type.__call__(self, *args)
 
         # 生成したインスタンスの属性を設定する
         for name in kwargs:
             setattr(obj, name, kwargs[name])
 
         # 生成したインスタンスを返す
         return obj
```

このメタクラスはインスタンスの生成を上書きしているだけで、他の機能はまだ `type` が処理している。

さて、このメタクラスを用いて `Car` クラスを書き直すことが可能である。Python 2ではクラス定義中で `__metaclass__` にこのメタクラスを代入すればよい(Python 3では代わりに `metaclass=M` と名前付き引数として与える)。

```python
class Car(object):
     __metaclass__ = AttributeInitType
     __slots__ = ['make', 'model', 'year', 'color']
 
     @property
     def description(self):
         """ Return a description of this car. """
         return "%s %s %s %s" % (self.color, self.year, self.make, self.model)
```

これで、`Car` のインスタンスを次のように生成できる。

```python
cars = [
     Car(make='Toyota', model='Prius', year=2005, color='green'),
     Car(make='Ford', model='Prefect', year=1979, color='blue')]
```


## 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ボタン（古典的なクラスブラウザではクラス一覧を表示する枠に設置されている）を押して表示を切り替えることで対応するメタクラスの定義にアクセスしたりその内容（クラスインスタンス変数やクラスメソッド）を編集可能になっている。

クラスおよびメタクラスの振る舞いは次の4段階の継承階層を経て定義されている。

:Object - インスタンス・クラスの別なく、オブジェクトとしての普遍的な振る舞い
::Behavior - クラスの最低限の振る舞い（コンパイルされたメソッドの保持やインスタンス生成）
:::ClassDescription (抽象クラス) - クラスの振る舞い（メソッドのコンパイルやカテゴリ管理）
::::Class - 通常のクラスの振る舞い（スーパークラスとしての振る舞いやクラス分類など）
::::Metaclass - メタクラス独自の振る舞い（一部メッセージをクラスにリダイレクトするなど）

## Rubyにおけるメタクラス
Rubyでは、クラス自体がClassというクラスのインスタンスであり、`Class.new`という形でクラスを動的に生成することもできる。ClassはModuleを継承しており、動的なメソッドの操作といったクラスに共通な機能があるほか、特異メソッド（あるオブジェクトだけに有効なメソッド）を使うことで、Smalltalk-76のような単一のメタクラスでクラスごとの多様性をもたせることができる。
具体的には、存在しないメソッドの呼び出しや、継承・メソッドの追加といったタイミングで呼び出されるフック関数を特異メソッドとして実装することができる。

## 利用可能な言語とツール
有名なプログラミング言語でメタクラスが利用可能なものは以下である。
* Common Lisp
* Groovy
* Object Pascal (中でもDelphiが代表的である)
* Objective-C
* Ruby
* Python
* Perl(メタクラスプラグマまたはMooseを用いて)
* Smalltalk

次のようにそれほど普及していない言語の中にはメタクラスが利用できるものもある。いくつかは研究目的であり、1990年代初頭にまで遡る: OpenJavaやOpenC++、OpenAda、CorbaScript、ObjVLisp、Object-Z、MODEL-K、XOTcl、MELDCなど。

また、Prologのオブジェクト指向拡張であるLogtalkでもメタクラスが利用できる。

さらに、Resource Description Framework (RDF)とUnified Modeling Language (UML)は両者共にメタクラスが利用できる。

## 関連項目
*メタモデル
*メタプログラミング
*リフレクション
*Adapter パターン

## 出典

## 参考文献
*