Ruby言語やLinuxのネタが多いです。
August 18, 2002 [おもひで]
■ [Ruby] Allocation Frameworkで悩む
Ruby-1.7系の場合、メソッドnewは allocate -> initializeという順番で初期化を行って行くんだけど、じゃぁ、いったいallocateでは何をしてinitializeでは何をすべきか、というところではまった。
具体的にはRuby/GTK2のGdk::Cursor用コード(の抜粋版)。
static VALUE gdkcursor_s_allocate(klass)
VALUE klass;
{
GdkCursor c;
return Data_Make_Struct(klass, GdkColor, 0, free, c);
}
static VALUE
gdkcursor_initialize(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
VALUE source, mask, fg, bg, x, y;
rb_scan_args(argc, argv, "15", &source, &mask, &fg, &bg, &x, &y);
DATA_PTR(self) = gdk_cursor_new(NUM2INT(source));
return self;
}
■ 今のCVS版だと上記の(ような)実装になってるのだけど、これだと、allocateの方で生成したGdkColorが無駄になってしまう。
うーん、どうすれば良いんだ....と思ってruby-devの過去メールをあさると立石さんが同様の問題で悩まれていたようで、そのものずばりのスレッドがあった。ホント、読んでないよね<オレ。
■ で、この辺の情報ってどこかにまとまってないのかなぁ、と思いつつスレッドの内容をまとめてみた
Allocation Frameworkは「allocationのやり方がオブジェクトごとに異なっていて、どこにフックをかけたらよいのかわからない」という問題を解決するもの。 これにより、
「すべてのクラス」で「未初期化のRubyオブジェクト」を返すべき。
allocateはごくまれに生成されるインスタンスのタイプや構造を知るためにも使われるので、できるだけなにもしない「空のRubyオブジェクト」を返したほうが良い。
initializeはサブクラスでオーバーライドされる可能性がある
と統一されたので、生成と初期化について一貫性ができた。しかも、やや間接的ではあるが、クラスからそのクラスのインスタンスの「型」を知る方法ができたという副次的な効果もできた。
T_DATAの場合にはptrを0としてData_Wrap_Structするのがよい。で、initializeで DATA_PTR(obj) = ptr と初期化する。 それ以外の「型」については個別に対応する必要があるが、「型」を自分で定義する機会は滅多に無いはず。
■ ということは、T_DATAである上記コードは以下のように書けば良いのかな。
static VALUE gdkcursor_s_allocate(klass)
VALUE klass;
{
return Data_Wrap_Struct(klass, 0, free, 0);
}
initializeの方は同じ。
■ んでもって
また,allocateで使用不能なオブジェクトを作ったことで,すべてのメソッドでその使用不能状態を検出する作業が必要になるなどの場合があると思います.このような場合でもallocateで使用不能状態を作るべきかでちょっと悩んでしまいます.
これはinitializeする前だけでなく、たとえばcloseされたIOなんかにも当てはまる話です。Rubyが静的な(変数でなく)オブジェクトのスコープ(というよりライフスパンといったほうが適切?)を持たない以上、対応は必須だと思います。
ProcやThreadのように使用不能な状態の存在しないクラスもありますので、絶対にだめとは言えませんが、従っておいたほうがユーザに親切ではないだろうかとは思います。ProcやThreadも将来的には対応させようと思ってますし。
これって、あおきさんみたいにinitializeしていない場合はエラーを返すようにしないといけないということかな。となると上記のように単純にData_Wrap_Struct使うだけじゃダメだね....。
■ とここまで考えてさかいさんのRuby/GLibのコードを読み直す
gobj_holderが良い感じだ。そうか、こうすれば良いのか。さすがさかいさん...。
■ それにしても
まったく、ここまで何も理解してないでメンテナやってるオレもすごいな(^^;)。

ブラボーな、まとめだと思われ。
自分の頭の中を整理したいときって、書かないとだめなんですよね〜、私の場合(^^;)。