ソースを見てみる

Rubyソースコード完全解説を見ながらソースをチェック。object.c の以下の部分の理解が微妙であり、第4章 クラスとモジュールを熟読中。

void
Init_Object()
{
    VALUE metaclass;

    rb_cObject = boot_defclass("Object", 0);
    rb_cModule = boot_defclass("Module", rb_cObject);
    rb_cClass =  boot_defclass("Class",  rb_cModule);

    metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
    metaclass = rb_make_metaclass(rb_cModule, metaclass);
    metaclass = rb_make_metaclass(rb_cClass, metaclass);

    rb_mKernel = rb_define_module("Kernel");
    rb_include_module(rb_cObject, rb_mKernel);
    rb_define_alloc_func(rb_cObject, rb_class_allocate_instance);
    rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, 0);
    rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
    rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);


    rb_define_method(rb_mKernel, "nil?", rb_false, 0);
(以下略)

再読三読四読 ...
# class.c も見つつ

追記

うーん。分かったような分からないような。
とりあえず、object.c において Class と Object と Module 関連の手続きを抜き出してみる。まず、Object について。

   rb_cObject = boot_defclass("Object", 0);
   metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
   rb_include_module(rb_cObject, rb_mKernel);
   rb_define_alloc_func(rb_cObject, rb_class_allocate_instance);
   rb_define_private_method(rb_cObject, "initialize", rb_obj_dummy, 0);
   ruby_top_self = rb_obj_alloc(rb_cObject);

記述がつながっているように見えますが grep の出力です。上から順に

  • クラスの定義 (スーパークラスは無し)
  • メタクラスの生成 (クラスメソドの定義、と決めうち)
  • Kernel モジュールの include
  • allocate メソドの定義
  • initialize (プライベートメソド) の定義
  • rb_obj_alloc で実体の生成??

rb_obj_alloc 関数については、第5章 ガーベージコレクション に記述あり。allocate はしてますが initialize は Qnil 返却する関数になってるし initialize してない風に見える。ちなみに現行のリファレンスマニュアルにも何もしない、と書いてあるんで上記の理解でセイフかなぁ。


ちなみに

   metaclass = rb_make_metaclass(rb_cObject, rb_cClass);

ですが、Object のメタクラス (特異クラス) を生成していて、それは Class を継承している、という読み方でセイフかなぁ。という事は Class で定義されているメソドはクラスメソドとして Object に実装される、と考えて良いのだろうか。
という事は、Class において定義されている

   rb_define_method(rb_cClass, "allocate", rb_obj_alloc, 0);
   rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
   rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
   rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy,
1); /* in class.c */
   rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);

等は Object のクラスメソドとして継承されるの??
それぞれ 1.8.5 な irb で確認を。

irb(main):001:0> Object.allocate
=> #<Object:0x40235060>
irb(main):002:0> Object.new
=> #<Object:0x40231960>
irb(main):003:0> Object.initialize
NoMethodError: private method `initialize' called for Object:Class
       from (irb):3
       from :0
irb(main):004:0> Object.initialize_copy
NoMethodError: private method `initialize_copy' called for Object:Class
       from (irb):4
       from :0
irb(main):005:0> Object.superclass
=> nil
irb(main):006:0>

うーん。initialize は object.c の Init_Object() で private 化しているんですが、initialize_copy はどこで操作しているのだろうか。って現行マニュアルの Object クラスの説明において以下のような記述を発見。

initialize_copy という名前のメソッドは自動的に private に設定されます。

なにー。根拠は何だ、と言いつつ initialize_copy で grep かけたら

./doc/ChangeLog-1.8.0:  * eval.c (rb_add_method): initialize_copy should always
be

みたいな出力が。doc/ChangeLog-1.8.0 を覗いてみると

Mon May 19 13:58:03 2003  Yukihiro Matsumoto  <matz@ruby-lang.org>

       * object.c (init_copy): rename copy_object as initialize_copy,
         since it works as copy constructor.

       * eval.c (rb_add_method): initialize_copy should always be
         private, like initialize.

とある。eval.c の rb_add_method ですか。このあたりの処理??

   if (!FL_TEST(klass, FL_SINGLETON) &&
       node && nd_type(node) != NODE_ZSUPER &&
       (mid == rb_intern("initialize" )|| mid == rb_intern("initialize_copy"))) {
       noex = NOEX_PRIVATE | noex;
   }

キッツいなぁ。Rubyソースコード完全解説をきっちり読まないと駄目そげ。


ってーか、何してるんだかワケワカ状態だ。何しようとしてたのか、というとマニュアル原本とソースの整合性を確認しようとしてたんだった。とりあえず、マニュアルのソースからメソド部分を抜き出してみた。

$ grep '^---' refm/api/src/_builtin/Object|sort -k 2
--- ==(other)
--- ===(other)
--- =~(other)
--- __id__
--- __send__(name, *args)
--- __send__(name, *args) { .... }
--- _dump(limit)
--- class
--- clone
--- display(out = $stdout)
--- dup
--- enum_for(method = :each, *args)
--- eql?(other)
--- equal?(other)
--- extend(*modules)
--- freeze
--- frozen?
--- hash
--- id
--- initialize
--- initialize_copy(obj)
--- inspect
--- instance_eval {|obj| ... }
--- instance_eval(expr, filename = '(eval)', lineno = 1)
--- instance_of?(klass)
--- instance_variable_defined?(symbol)
--- instance_variable_get(var)
--- instance_variable_set(var, val)
--- instance_variables
--- is_a?(mod)
--- kind_of?(mod)
--- marshal_dump
--- marshal_load(obj)
--- method(name)
--- method_missing(name, *args, &block)
--- methods
--- methods([inherited_too])
--- new
--- nil?
--- object_id
--- private_methods
--- private_methods([inherited_too])
--- protected_methods
--- protected_methods([inherited_too])
--- public_methods
--- public_methods([inherited_too])
--- remove_instance_variable(name)
--- respond_to?(name, include_private = false)
--- send(name, *args)
--- send(name, *args) { .... }
--- singleton_method_added(name)
--- singleton_method_removed(name)
--- singleton_method_undefined(name)
--- singleton_methods
--- singleton_methods(inherited_too = false)
--- singleton_methods(inherited_too = true)
--- taint
--- tainted?
--- to_a
--- to_ary
--- to_enum(method = :each, *args)
--- to_hash
--- to_int
--- to_s
--- to_str
--- type
--- untaint
$

マニュアルのソースにおいて、クラスメソドとして記述されているのは new だけ。それ以外は instance methods として記述されているんですが、現時点で全部ヒモが付いていない感じ。
とりあえず Object は Kernel モジュール を include してるんで Kernel 関連も抜き出してみる。でもまだ足りてない感じ。

   rb_mKernel = rb_define_module("Kernel");

   rb_define_method(rb_mKernel, "nil?", rb_false, 0);
   rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
   rb_define_method(rb_mKernel, "equal?", rb_obj_equal, 1);
   rb_define_method(rb_mKernel, "===", rb_equal, 1);
   rb_define_method(rb_mKernel, "=~", rb_obj_pattern_match, 1);

   rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);

   rb_define_method(rb_mKernel, "id", rb_obj_id_obsolete, 0);
   rb_define_method(rb_mKernel, "type", rb_obj_type, 0);
   rb_define_method(rb_mKernel, "class", rb_obj_class, 0);

   rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
   rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
   rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);

   rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
   rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
   rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
   rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
   rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);

   rb_define_method(rb_mKernel, "to_a", rb_any_to_a, 0); /* to be removed */
   rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
   rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
   rb_define_method(rb_mKernel, "methods", rb_obj_methods, -1);
   rb_define_method(rb_mKernel, "singleton_methods",
                    rb_obj_singleton_methods, -1); /* in class.c */
   rb_define_method(rb_mKernel, "protected_methods",
                    rb_obj_protected_methods, -1);
   rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, -1);

   rb_define_method(rb_mKernel, "public_methods", rb_obj_public_methods, -1);
   rb_define_method(rb_mKernel, "instance_variables",
                    rb_obj_instance_variables, 0); /* in variable.c */
   rb_define_method(rb_mKernel, "instance_variable_get", rb_obj_ivar_get, 1);
   rb_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set, 2);
   rb_define_private_method(rb_mKernel, "remove_instance_variable",
                            rb_obj_remove_instance_variable, 1); /*
in variable.c */

   rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
   rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
   rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);

   rb_define_private_method(rb_mKernel, "singleton_method_added",
rb_obj_dummy, 1);
   rb_define_private_method(rb_mKernel, "singleton_method_removed",
rb_obj_dummy, 1);
   rb_define_private_method(rb_mKernel, "singleton_method_undefined",
rb_obj_dummy, 1);

うーむ。長い。

てーか、ぐだぐだ感満載だなぁ。