予想は当たっていたけれど調べ方がまずかったみたいです。
昨日の続きです。コメントで教えていただいたとおり、README.EXT.jaを読んでみました。結果、
void rb_define_method(VALUE klass, const char *name, VALUE (*func)(), int argc);
でklassというオブジェクトにnameという名前でfuncという操作をするメソッドを定義し*1、
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
でrecvのmidで指定したメソッドへargvを引数にとって呼び出すようです。昨日見たところは
rb_funcall2(obj, idInitialize, argc, argv);
ということなので、idInitializeが'#initialize'を指しているということになります。直前ではメモリを確保しているだけのようなので、やっぱり当初の予想「newでメモリを確保、initializeで初期化」は当たっていたようですね。間がわかりませんが…
idInitializeに何が入っているか気になったのですが、ソースを落としてgrepをかけても、なぜか値を代入されていると思しきところをついに見なかったので、いつどこで何を代入されているのかわかりませんでした。
今度はObject#initializeの定義を見てみましょう。
//object.cの1621行目から static VALUE rb_class_initialize(int argc, VALUE *argv, VALUE klass) { VALUE super; if (RCLASS_SUPER(klass) != 0 || klass == rb_cBasicObject) { rb_raise(rb_eTypeError, "already initialized class"); } if (argc == 0) { super = rb_cObject; } else { rb_scan_args(argc, argv, "01", &super); rb_check_inheritable(super); if (super != rb_cBasicObject && !RCLASS_SUPER(super)) { rb_raise(rb_eTypeError, "can't inherit uninitialized class"); } } RCLASS_SUPER(klass) = super; rb_make_metaclass(klass, RBASIC(super)->klass); rb_class_inherited(super, klass); rb_mod_initialize(klass); return klass; }
名前から察するに、継承の親子関係はここで設定するようです。あとはメタクラスを作成してオブジェクトを返してあげます。
…それはいいんだけどinitializeの中身はどこで実行してるんだろう…おそらくrb_mod_initializeの先だと思うんですが…
*1:実は16個以上の引数を定義できない仕様らしいということがついでに分かりました。括弧書きでことわりのある通り、仮に大量のオプションが必要だとしても、ハッシュでまとめてしまえば「要りませんよね,そんなに」