【コラム】
今回は、クラス構造体のうち、クラス情報のフィールドを取り上げよう。isaとsuper_classだ。
クラス構造体には、isaとsuper_classというフィールドがある。どちらも、クラス構造体(struct objc_class)へのポインタだ。super_classの正体は予想がつくと思う。このクラスの親クラスへのポインタだ。では、isaとは何か?
isaの意味は、「このオブジェクトの定義となるオブジェクト」ということになる。たとえば、オブジェクトAのisaがオブジェクトBである場合、オブジェクトAの定義はオブジェクトB。つまり、"ObjectA is an ObjectB"と、考えればいい。
これでは概念的すぎるので、もっと実践的に考えてみよう。まず、isaは、クラスとインスタンスオブジェクトの間でも使われる。後日説明するが、インスタンスオブジェクトもisaフィールドを持っているのだ。この場合、このフィールドは自分自身が属するクラスを指すことになる。たとえば、NSStringのインスタンスオブジェクトのisaは、NSStringのクラスになる。
そして、そのNSStringクラスだが、これもisaフィールドを持っている。上の考え方によれば、ここには「NSStringクラスの定義となるオブジェクト」が入ることになる。クラスの定義となるオブジェクトとは何か?
Objective-Cでは、クラスもオブジェクトとして扱う。オブジェクトとは、その定義より作成されて、メッセージを処理することができるもの、だ。つまり、インスタンスオブジェクトがその定義であるクラスより作られるように、クラスオブジェクトもその定義が必要になる。これをクラスのクラスという意味で、メタクラスと呼ぶ。NSStringクラスのisaフィールドには、NSStringメタクラスへのポインタが入るのだ 。
メタクラスは、クラスのためのクラスだ。メタクラスとクラスの間の関係は、クラスとインスタンスの間の関係と似たものになる。
たとえば、NSStringクラスは、NSStringインスタンスのためのインスタンスメソッドを管理する。それと同様に、NSStringメタクラスは、クラスメソッドを管理することになる。インスタンスメソッドとクラスメソッドは、実装レベルで見れば、管理するクラス構造体が違っている。
ただし、インスタンス変数は同じようには扱われない。クラスにはインスタンス変数の定義があるが、メタクラスにはそれに対応するものがない。Objective-Cでは、クラス変数のための文法がないためである。これは、しばしば、Objective-Cの文法に一貫性がないとして指摘されるところである。実践的には、実装ファイルでstatic変数を宣言することで、クラス変数として利用する。
クラスとメタクラスは、ともにクラス構造体、つまりstruct objc_classになる。そこで、区別をつけるために、infoフィールドが使われる。infoフィールドは、その構造体の情報を表すフラグを格納する。その構造体がクラスのためのものであればCLS_CLASS (0x1L)の、メタクラスであればCLS_META (0x2L)のフラグが立つ。
メタクラスにも、isaとsuper_classフィールドがある。これらは何を指すのであろうか?
まず確認しておくが、メタクラスはオブジェクトではない。メタメタクラスは存在しないのである。したがって、メタクラスのisaフィールドは、意味をなさないと考えることができる。一応、Mac OS Xの実装では、このフィールドにはNSObjectメタクラスへのポインタが入っている。これは、便宜的なものではないだろうか。
super_classの方には、メタクラスの親メタクラスへのポインタが入る。NSStringメタクラスならば、NSObjectメタクラスになる。親クラスが指定されているということは、メタクラスでも、継承を用いたメソッド呼び出しが行われるということだ。たとえば、NSStringのクラスメソッドを呼び出すと、まずNSStringメタクラスにメソッドを探しにいき、そこになければ親クラスであるNSObjectメタクラスで探すことになる。インスタンスメソッドでの呼び出し方と同じだ。
では、ルートクラスのメタクラスである、NSObjectメタクラスの親クラスはどうなっているのか?実は、NSObjectクラスになっている。少しややこしいことになるが、すべてのメタクラスの継承構造をたどっていくと、NSObjectメタクラスを経由して、最終的にNSObjectクラスにたどり着くことになる。つまり、メタクラスのルートクラスも、NSObjectクラスなのだ。
これでどうなるかというと、クラスメソッドの探索は、最終的にNSObjectクラスに行き着く。ということは、クラスオブジェクトで、すべてのNSObjectのインスタンスメソッドが使える、ということになる。
メタラクスを導入する利点は、クラスもオブジェクトとみなせること。さらに、プログラマの立場からすると、クラスオブジェクトでもNSObjectのインスタンスメソッドが使えることだ。
NSObjectのインスタンスメソッドには、同一性をチェックするisEqual:、クラスをチェックするisKindOfClass:、ハッシュ値を得るhash、セレクタを指定して実行するperformSelector:などがあるが、これらがすべて使える。つまり、コンテナクラスであるNSArrayやNSDictionaryで、そのままクラスオブジェクトを扱える。実際にクラスを使ってプログラミングする際に、非常に有用だ。
が、実際には、Objective-Cでのプログラミングの際に、メタクラスの存在を意識することは少ない。Smalltalkなどの環境と比べると、その利用機会は控えめであろう。
| トマトを食べれば痩せられる!? -京大ら、新発見の成分で肥満改善効果を実証 [21:00 2/10] |
| JAXA、液体シリコン中に残存する共有結合を観察 -大口径ウェハの実現に期待 [20:11 2/10] |
| NEDOなど、熱膨張が小さな樹脂複合材料ペレットの量産化に成功 [19:22 2/10] |
| 理研、一般顕微鏡を蛍光顕微鏡に強化できるアダプタを試作して性能を実証 [19:15 2/10] |
| 天の川のブラックホールが小惑星を飲み込んでいる - NASAが発表 [18:08 2/10] |
|
坂本教授、木の光合成に着目した不思議な音楽的挑戦!『ETV特集』 [10:08 2/11] キャリア |
|
バロックで異端!水墨画の巨匠、雪村周継の神業に迫る! [10:07 2/11] キャリア |
|
元・宝塚の真琴つばさ、ドラマ初主演で小学生の母親役に挑戦! [10:07 2/11] キャリア |
|
「四大陸フィギュア」今夜は連覇のかかった高橋、昨年末復活した浅田、村上に注目! [10:07 2/11] キャリア |
|
【EU発!Breaking News】精神疾患治療のため?マラリア患者の血液を注射された男性。(オーストリア) [10:05 2/11] キャリア |