トップ » 技術記事 » RHG 片手に Ruby 1.9 を読む集い(The RHG Strikes Back)に参加した(3) - 第3回 RHG の逆襲

RHG 片手に Ruby 1.9 を読む集い(The RHG Strikes Back)に参加した(3) - 第3回 RHG の逆襲 はてなブックマーク数 このエントリーをブックマークに追加

クラスとメタクラス

詳細は RHG を参照して欲しいのですが、Ruby の世界ではクラスもまたオブジェクトとして扱われます。Ruby ではそのクラスのオブジェクトに特異メソッドを定義することで、クラスにスタティックなメソッド(クラスメソッド)を定義しています。

言い換えると、クラスにスタティックなメソッド(クラスメソッド)を定義するとそのクラスの特異クラスのメソッドとして定義されるということになります。クラスのクラスであるため、クラスの特異クラスをメタクラスと呼びます。

以下の図を見ると、Class クラスはメタクラスの親クラスになっていることがわかります。Ruby ユーザーからはクラスは Class クラスのインスタンスですが、C レベルでは特異クラスがメタクラスとして間に挟まっていることがわかります。

クラスとメタクラス(by Kodougu


クラスの継承構造に従ってメタクラスも継承することに注意してください。これは、「メタクラスを継承させることで、子クラスでも親クラスで定義したクラスメソッドを呼び出せるようにするため」と考えられます。
(2008/4/9 星さんにいただいたコメントにより追記。)

特異クラスは特異メソッドを定義した際に定義されます。しかし、メタクラスはクラスが定義されたときに特異メソッドの有無に関わらず生成されます。同じ特異クラスでありながら扱いが異なる理由は、勉強会では、「クラスの場合、特定のクラスの特異クラスを作ると親クラスの特異クラスも同時に生成しなければならないため、あらかじめ作成しておくのではないか」という指摘がありました。

クラスの継承とモジュールのインクルード

Ruby には、mixin を実現するためのモジュールという機構があります。モジュールは一見すると多重継承のような機構に見えますが、Ruby の世界では単一継承モデルで実装されています。

モジュールのインクルード(by Kodougu

図の通り、モジュールをインクルードすると、Ruby ユーザーから見えないクラス(RHGでは化身クラス)を生成して継承の間に挟み込むということをしています。

その他

勉強会では、Ruby の挙動が怪しい(バグ、もしくは仕様がない?)ところを見つけてしまうこともたまにあります。今回の勉強会で見つかった怪しいところは、さんがレポートしているので、あわせて参照してください。

まとめ

以上、第3回RHGの逆襲でした。特異クラス、メタクラス、モジュールのインクルードなどを実現するために、Ruby からは見えないクラスを C レベルで作成していることがわかりました。この概念を押さえておけば、難解なクラス・メソッドの定義も多少読みやすくなることでしょう。

さて、次回勉強会では、Ruby のガベージコレクションの仕組みを学習する予定です。RHG的には、第5章 ガ-ベージコレクションに相当します。もし次回から参加される方がいれば、少なくとも RHG で紹介されているガベージコレクションの仕組みは予習しておく必要があるでしょう。

主催者の皆様、有意義な勉強会をありがとうございました。次回も参加することができたら、本ブログで紹介したいと思います。それでは!

Series Navigation«第2回 RHG の逆襲第4回 RHG の逆襲»

1 2

このサイトについて

八角研究所
株式会社八角研究所のWEBサイトですよー。 いろんなものを創り出すことのできる環境をコツコツ構築中。 いったい、いつになったらできるのか。 この技術情報サイトもそのための活動の一環のつもり。

執筆者紹介

あかさた

あかさた

未踏(2006年度下期)でWeb上で動作するモデリング環境 Kodougu の開発をしてました。こちらでもブログを書いています。

TrackBack URL :

先日はお疲れ様でした。個人的にもいろいろアドバイスを賜り、ありがとうございました。

なぜ「クラスの特異クラス同士が継承しあうのか」も説明したほうがよいかと存じます。僕の考える理由は、「そうすると便利だから」というものです。たとえば:

class A; def self.foo; end; end
class B < A; end

で B.foo を呼べるようにするためではないかと思っています。

クラスの特異クラスが継承関係であるようになっているのは必然ではなく、 rb_make_metaclass 関数をつかってそうなるように仕向けているからなので、そのようにした理由が何かしらあるはずです。

コメントありがとうございます!
また、勉強会ではお疲れさまでした。

RHG にも「クラスの特異クラス自身がクラスと連動して継承するため、
クラスメソッドが継承される」と書かれていますから、おっしゃる
とおりクラスメソッドの継承を意図しての実装と考えられます。

確かにそこを説明しないと、読み手にかなりの想像力を要求することに
なりそうですので、後ほど対応しておきます。

だんだんと勉強会の内容が濃くなっていっているため、記事に起こせる
内容がごく限られた範囲になってきました。どこかで勉強会の成果を
ある程度網羅して形に残す機会を作りたいですね。