第4章 クラスとモジュール




CRuby

API


rb_define_class()

rb_define_class_under()

rb_define_module()

rb_define_module_under()

rb_define_method()

rb_define_singleton_method()


API


rb_define_class() RubyArray

Array
  19  VALUE rb_cArray;

1809  void
1810  Init_Array()
1811  {
1812      rb_cArray  = rb_define_class("Array", rb_cObject);

(array.c)

rb_cObjectrb_cArrayRubyObjectArray rubyrb cruby

rb_define_class()Object Arrayrb_define_class() RubyArray Ruby
class Array < Object

end rb_define_class()


rb_define_class_under() stat(2)File::Stat
File::Stat
  78  VALUE rb_cFile;
  80  static VALUE rb_cStat;

2581      rb_cFile = rb_define_class("File", rb_cIO);
2674      rb_cStat = rb_define_class_under(rb_cFile, "Stat", rb_cObject);

(file.c)

Ruby
class File < IO
  class Stat < Object

end


rb_define_module()

Enumerable
  17  VALUE rb_mEnumerable;

 492      rb_mEnumerable = rb_define_module("Enumerable");

(enum.c)

rb_mEnumerablemc Ruby
module Enumerable

rb_define_module_under()使


rb_define_method() 使Array

Array#to_s
1818  rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);

(array.c)

Arrayto_s rb_ary_to_s to_s0 Ruby
class Array < Object
  def to_s
    # rb_ary_to_s()の中身
  end
end

classrb_define_method() defclass class



Array#concat
1835  rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);

(array.c)

rb_cArrayArrayconcat rb_ary_concat()1 Ruby
class Array < Object
  def concat( str )
    # rb_ary_concat()の中身
  end
end


1Ruby File.unlinkFile.unlink File.link
File.link
2624  rb_define_singleton_method(rb_cFile, "link", rb_file_s_link, 2);

(file.c)

rb_define_method()使 rb_cFile


Init_xxxx() ArrayInit_Array()

Init_Array
1809  void
1810  Init_Array()
1811  {
1812      rb_cArray  = rb_define_class("Array", rb_cObject);
1813      rb_include_module(rb_cArray, rb_mEnumerable);
1814
1815      rb_define_singleton_method(rb_cArray, "allocate",
                                     rb_ary_s_alloc, 0);
1816      rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
1817      rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
1818      rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);
1819      rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
1820      rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
1821      rb_define_method(rb_cArray, "to_ary", rb_ary_to_a, 0);
1822      rb_define_method(rb_cArray, "frozen?",  rb_ary_frozen_p, 0);

(array.c)

Initruby inits.c

rb_call_inits()
  47  void
  48  rb_call_inits()
  49  {
  50      Init_sym();
  51      Init_var_tables();
  52      Init_Object();
  53      Init_Comparable();
  54      Init_Enumerable();
  55      Init_Precision();
  56      Init_eval();
  57      Init_String();
  58      Init_Exception();
  59      Init_Thread();
  60      Init_Numeric();
  61      Init_Bignum();
  62      Init_Array();

(inits.c)

Init_Array()


require "myextention"

myextention.so Init_myextention()extern 18Init

ruby stringio

Init_stringio()
 895  void
 896  Init_stringio()
 897  {
 898      VALUE StringIO = rb_define_class("StringIO", rb_cData);
 899      rb_define_singleton_method(StringIO, "allocate",
                                     strio_s_allocate, 0);
 900      rb_define_singleton_method(StringIO, "open", strio_s_open, -1);
 901      rb_define_method(StringIO, "initialize", strio_initialize, -1);
 902      rb_enable_super(StringIO, "initialize");
 903      rb_define_method(StringIO, "become", strio_become, 1);
 904      rb_define_method(StringIO, "reopen", strio_reopen, -1);

(ext/stringio/stringio.c)

rb_define_singleton_method()


m_tbl

rb_define_singleton_method()
 721  void
 722  rb_define_singleton_method(obj, name, func, argc)
 723      VALUE obj;
 724      const char *name;
 725      VALUE (*func)();
 726      int argc;
 727  {
 728      rb_define_method(rb_singleton_class(obj), name, func, argc);
 729  }

(class.c)

rb_define_method()使 rb_singleton_class()singleton class

使 RubyRuby 姿

rb_singleton_class()


call graph使
rb_define_singleton_method
    rb_define_method
    rb_singleton_class
        SPECIAL_SINGLETON
        rb_make_metaclass
            rb_class_boot
            rb_singleton_class_attached

static call graph dynamic call graph

rb_define_singleton_method() rb_define_method()rb_singleton_class() rb_singleton_class()SPECIAL_SINGLETON() rb_make_metaclass() cflow\footnote{cflowCD-ROMdoc/callgraph.html} 使

ruby CD-ROMdoc/callgraph.html
rb_singleton_class() rb_singleton_class()









rb_define_class() rb_define_class() rb_define_class()
rb_define_class
    rb_class_inherited
    rb_define_class_id
        rb_class_new
            rb_class_boot
        rb_make_metaclass
            rb_class_boot
            rb_singleton_class_attached

rb_class_new()

rb_class_new()
  37  VALUE
  38  rb_class_new(super)
  39      VALUE super;
  40  {
  41      Check_Type(super, T_CLASS);
  42      if (super == rb_cClass) {
  43          rb_raise(rb_eTypeError, "can't make subclass of Class");
  44      }
  45      if (FL_TEST(super, FL_SINGLETON)) {
  46          rb_raise(rb_eTypeError, "can't make subclass of virtual class");
  47      }
  48      return rb_class_boot(super);
  49  }

(class.c)

Check_Type() rb_raise() rb_class_boot()

rb_class_boot()
  21  VALUE
  22  rb_class_boot(super)
  23      VALUE super;
  24  {
  25      NEWOBJ(klass, struct RClass);        /* struct RClassを割り当てる */
  26      OBJSETUP(klass, rb_cClass, T_CLASS); /* RBasic部分の初期化 */
  27
  28      klass->super = super;       /*(A)*/
  29      klass->iv_tbl = 0;
  30      klass->m_tbl = 0;
  31      klass->m_tbl = st_init_numtable();
  32
  33      OBJ_INFECT(klass, super);
  34      return (VALUE)klass;
  35  }

(class.c)

NEWOBJ()OBJSETUP()struct Rxxxx Ruby NEWOBJ()struct RClassklass OBJSETUP()RClassRBasic basic.klassbasic.flags

OBJ_INFECT()

Asupersuper rb_class_boot()super
rb_class_boot()rb_class_new()

rb_singleton_class()
rb_singleton_class
    SPECIAL_SINGLETON
    rb_make_metaclass
        rb_class_boot
        rb_singleton_class_attached

rb_class_boot() rb_singleton_class()rb_make_metaclass()

rb_singleton_class()


rb_singleton_class()

rb_singleton_class()
 678  #define SPECIAL_SINGLETON(x,c) do {\
 679      if (obj == (x)) {\
 680          return c;\
 681      }\
 682  } while (0)

 684  VALUE
 685  rb_singleton_class(obj)
 686      VALUE obj;
 687  {
 688      VALUE klass;
 689
 690      if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
 691          rb_raise(rb_eTypeError, "can't define singleton");
 692      }
 693      if (rb_special_const_p(obj)) {
 694          SPECIAL_SINGLETON(Qnil, rb_cNilClass);
 695          SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
 696          SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
 697          rb_bug("unknown immediate %ld", obj);
 698      }
 699
 700      DEFER_INTS;
 701      if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
 702          (BUILTIN_TYPE(obj) == T_CLASS ||
 703           rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj)) {
 704          klass = RBASIC(obj)->klass;
 705      }
 706      else {
 707          klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
 708      }
 709      if (OBJ_TAINTED(obj)) {
 710          OBJ_TAINT(klass);
 711      }
 712      else {
 713          FL_UNSET(klass, FL_TAINT);
 714      }
 715      if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
 716      ALLOW_INTS;
 717
 718      return klass;
 719  }

(class.c)



VALUE FixnumSymbol rb_special_const_p()VALUE Qtrue Qfalse Qnil VALUErb_bug()

DEFER_INTS()ALLOW_INTS()INTS rubysig.hINTSinterrupts

rb_make_metaclass()


rb_make_metaclass()
 142  VALUE
 143  rb_make_metaclass(obj, super)
 144      VALUE obj, super;
 145  {
 146      VALUE klass = rb_class_boot(super);
 147      FL_SET(klass, FL_SINGLETON);
 148      RBASIC(obj)->klass = klass;
 149      rb_singleton_class_attached(klass, obj);
 150      if (BUILTIN_TYPE(obj) == T_CLASS) {
 151          RBASIC(klass)->klass = klass;
 152          if (FL_TEST(obj, FL_SINGLETON)) {
 153              RCLASS(klass)->super =
                          RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
 154          }
 155      }
 156
 157      return klass;
 158  }

(class.c)

rb_class_boot()super FL_SINGLETON


VALUE

rb_singleton_class() rb_make_metaclass()
rb_singleton_class(obj)
{
    if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) &&
        (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) &&
        rb_iv_get(RBASIC(obj)->klass, "__attached__") == obj) {
        klass = RBASIC(obj)->klass;
    }
    else {
        klass = rb_make_metaclass(obj, RBASIC(obj)->klass);
    }
    return klass;
}

rb_make_metaclass(obj, super)
{
    klass = superをスーパークラスにしたクラスを生成;
    FL_SET(klass, FL_SINGLETON);
    RBASIC(obj)->klass = klass;
    rb_singleton_class_attached(klass, obj);
    if (BUILTIN_TYPE(obj) == T_CLASS) {
        RBASIC(klass)->klass = klass;
        if (FL_TEST(obj, FL_SINGLETON)) {
            RCLASS(klass)->super =
                    RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
        }
    }

    return klass;
}

rb_singleton_class()if rb_make_metaclass()

rb_make_metaclass()BUILTIN_TYPE()TYPE() T_xxxxobj obj



rb_singleton_class() rb_make_metaclass()
rb_singleton_class(obj)
{
    klass = RBASIC(obj)->klassをスーパークラスにしたクラスを生成;
    FL_SET(klass, FL_SINGLETON);
    RBASIC(obj)->klass = klass;
    return klass;
}

klass klasssclass

rb_singleton_class() rb_make_metaclass()
rb_singleton_class(obj)
{
    sclass = RBASIC(obj)->klassをスーパークラスにしたクラスを生成;
    FL_SET(sclass, FL_SINGLETON);
    RBASIC(obj)->klass = sclass;
    return sclass;
}

1

(addsclass)
1: rb_singleton_class

sclass klass


rb_singleton_class_attached()
rb_make_metaclass(obj, super)
{
    klass = superをスーパークラスにしたクラス生成;
    FL_SET(klass, FL_SINGLETON);
    RBASIC(obj)->klass = klass;
    rb_singleton_class_attached(klass, obj);   /* これ */



rb_singleton_class_attached()
 130  void
 131  rb_singleton_class_attached(klass, obj)
 132      VALUE klass, obj;
 133  {
 134      if (FL_TEST(klass, FL_SINGLETON)) {
 135          if (!RCLASS(klass)->iv_tbl) {
 136              RCLASS(klass)->iv_tbl = st_init_numtable();
 137          }
 138          st_insert(RCLASS(klass)->iv_tbl,
                        rb_intern("__attached__"), obj);
 139      }
 140  }

(class.c)

klassFL_SINGLETON klassiv_tbl __attached__obj klassFL_SINGLETON

__attached__@ Ruby 使

klassobjklassobj obj 使 objsingleton_method_added
__attached__ new







FL_SINGLETON



ClassClass Class2

(infloop)
2: 



RubyRuby



ClassClassClassClassClass  ClassClassClass ClassClass

ClassClass


Ruby









Ruby reflection Ruby

Ruby

Ruby

Ruby JavaC++

3

(reqlink)
3: 


Ruby
class A
  def A.test    # Aに特異メソッドを定義する
    puts("ok")
  end
end

class B < A
end

B.test()  # 呼べてしまう





rb_define_class()
rb_define_class
    rb_class_inherited
    rb_define_class_id
        rb_class_new
            rb_class_boot
        rb_make_metaclass
            rb_class_boot
            rb_singleton_class_attached

rb_make_metaclass() rb_singleton_class() rb_make_metaclass()使

rb_define_class_id()


rb_define_class_id()

rb_define_class_id()
 160  VALUE
 161  rb_define_class_id(id, super)
 162      ID id;
 163      VALUE super;
 164  {
 165      VALUE klass;
 166
 167      if (!super) super = rb_cObject;
 168      klass = rb_class_new(super);
 169      rb_name_class(klass, id);
 170      rb_make_metaclass(klass, RBASIC(super)->klass);
 171
 172      return klass;
 173  }

(class.c)

rb_class_new()super rb_name_class()name rb_make_metaclass() rb_singleton_class()
rb_make_metaclass(obj, RBASIC(obj)->klass);


rb_make_metaclass(klass, RBASIC(super)->klass);

rb_make_metaclass()

rb_make_metaclass


rb_make_metaclass
rb_make_metaclass(obj, super)
{
    klass = superをスーパークラスにしたクラスを生成;
    FL_SET(klass, FL_SINGLETON);
    RBASIC(obj)->klass = klass;
    rb_singleton_class_attached(klass, obj);
    if (BUILTIN_TYPE(obj) == T_CLASS) {
        RBASIC(klass)->klass = klass;
        if (FL_TEST(obj, FL_SINGLETON)) {
            RCLASS(klass)->super =
                    RBASIC(rb_class_real(RCLASS(obj)->super))->klass;
        }
    }

    return klass;
}

ifT_CLASS rb_define_class_id()
rb_make_metaclass(klass, RBASIC(super)->klass);

rb_make_metaclass()

rb_make_metaclass
rb_make_metaclass(klass, super_klass  /* == RBASIC(super)->klass */)
{
    sclass = super_klassをスーパークラスにした特異クラスを生成;
    RBASIC(klass)->klass = sclass;
    RBASIC(sclass)->klass = sclass;
    return sclass;
}

4 使 obj(obj)(klass) klass

(metaclass)
4: 

4c 5

(multi)
5: 

superklassklass klass2c(super) Object(Object)
class A < Object
end
class B < A
end

6

(metatree)
6: 



使調 7

(mmm)
7: 


ObjectClass 1Rubyclass()
p(Object.class())   # Class

RubyC (Object)Ruby(Object) Object#class rb_obj_class()

rb_obj_class()
  86  VALUE
  87  rb_obj_class(obj)
  88      VALUE obj;
  89  {
  90      return rb_class_real(CLASS_OF(obj));
  91  }

  76  VALUE
  77  rb_class_real(cl)
  78      VALUE cl;
  79  {
  80      while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {
  81          cl = RCLASS(cl)->super;
  82      }
  83      return cl;
  84  }

(object.c)

CLASS_OF(obj)objbasic.klassrb_class_real() 8

I_CLASS

(real)
8: 




Ruby

rb_make_metaclass() 使 使



ObjectModule Classrb_define_class()API Class Class ruby



Object Module Class
1243  rb_cObject = boot_defclass("Object", 0);
1244  rb_cModule = boot_defclass("Module", rb_cObject);
1245  rb_cClass =  boot_defclass("Class",  rb_cModule);
1246
1247  metaclass = rb_make_metaclass(rb_cObject, rb_cClass);
1248  metaclass = rb_make_metaclass(rb_cModule, metaclass);
1249  metaclass = rb_make_metaclass(rb_cClass, metaclass);

(object.c)

boot_defclass()rb_class_boot() 9

(Object) (Module) (Class) 9(Object)(Module) rb_make_metaclass()
(boot1)
9: 

姿10

(metaobj)
10: Ruby


rb_define_class()rb_define_class_under()


rb_define_class()

rb_define_class()
 183  VALUE
 184  rb_define_class(name, super)
 185      const char *name;
 186      VALUE super;
 187  {
 188      VALUE klass;
 189      ID id;
 190
 191      id = rb_intern(name);
 192      if (rb_autoload_defined(id)) {             /*(A)オートロード */
 193          rb_autoload_load(id);
 194      }
 195      if (rb_const_defined(rb_cObject, id)) {    /*(B)rb_const_defined */
 196          klass = rb_const_get(rb_cObject, id);  /*(C)rb_const_get */
 197          if (TYPE(klass) != T_CLASS) {
 198              rb_raise(rb_eTypeError, "%s is not a class", name);
 199          }                                      /*(D)rb_class_real */
 200          if (rb_class_real(RCLASS(klass)->super) != super) {
 201              rb_name_error(id, "%s is already defined", name);
 202          }
 203          return klass;
 204      }
 205      if (!super) {
 206          rb_warn("no super class for `%s', Object assumed", name);
 207      }
 208      klass = rb_define_class_id(id, super);
 209      rb_class_inherited(super, klass);
 210      st_add_direct(rb_class_tbl, id, klass);
 211
 212      return klass;
 213  }

(class.c)

rb_define_class_id()

ARuby rb_autoload_xxxx()

Bklassname

Cklassname 6

Drb_class_real()cICLASS superRuby





rb_define_class_id()
st_add_direct(rb_class_tbl, id, klass);

rb_class_tbl GC


pClass#name

rb_name_class()
rb_define_class
    rb_define_class_id
        rb_name_class



rb_name_class()
 269  void
 270  rb_name_class(klass, id)
 271      VALUE klass;
 272      ID id;
 273  {
 274      rb_iv_set(klass, "__classid__", ID2SYM(id));
 275  }

(variable.c)

__classid__Ruby VALUEIDID2SYM() Symbol


2


1 2 2rb_define_class_under()

rb_define_class_under()
 215  VALUE
 216  rb_define_class_under(outer, name, super)
 217      VALUE outer;
 218      const char *name;
 219      VALUE super;
 220  {
 221      VALUE klass;
 222      ID id;
 223
 224      id = rb_intern(name);
 225      if (rb_const_defined_at(outer, id)) {
 226          klass = rb_const_get(outer, id);
 227          if (TYPE(klass) != T_CLASS) {
 228              rb_raise(rb_eTypeError, "%s is not a class", name);
 229          }
 230          if (rb_class_real(RCLASS(klass)->super) != super) {
 231              rb_name_error(id, "%s is already defined", name);
 232          }
 233          return klass;
 234      }
 235      if (!super) {
 236          rb_warn("no super class for `%s::%s', Object assumed",
 237                  rb_class2name(outer), name);
 238      }
 239      klass = rb_define_class_id(id, super);
 240      rb_set_class_path(klass, outer, name);
 241      rb_class_inherited(super, klass);
 242      rb_const_set(outer, id, klass);
 243
 244      return klass;
 245  }

(class.c)

rb_define_class()rb_define_class_id() rb_define_class() rb_set_class_path()

rb_set_class_path()


underklassname class path Net::NetPrivate::Socket

rb_set_class_path()
 210  void
 211  rb_set_class_path(klass, under, name)
 212      VALUE klass, under;
 213      const char *name;
 214  {
 215      VALUE str;
 216
 217      if (under == rb_cObject) {
              /* トップレベルに定義した */
 218          str = rb_str_new2(name);    /* nameからRubyの文字列を作る */
 219      }
 220      else {
              /* ネストした定義 */
 221          str = rb_str_dup(rb_class_path(under));  /* 返り値をコピー */
 222          rb_str_cat2(str, "::");     /* それに"::"を連結 */
 223          rb_str_cat2(str, name);     /* それにnameを連結 */
 224      }
 225      rb_iv_set(klass, "__classpath__", str);
 226  }

(variable.c)

__classpath__Ruby rb_name_class()__classid__ id
__classpath__    Net::NetPrivate::Socket
__classid__                       Socket

rb_define_class()__classid__ __classpath__under rb_class_path()


__classpath____classid__ Ruby使
c = Class.new()

rb_define_class_id() c


SomeClass = c   # クラス名はSomeClass

SomeClasspClass#name rb_class_tbl
class A
  class B
    C = tmp = Class.new()
    p(tmp)   # ここで名前が検索される
  end
end




rb_include_module1


Module#include Crb_include_module() rb_mod_include()Module#append_features rb_include_module() RubyC
Module#include (rb_mod_include)
    Module#append_features (rb_mod_append_features)
        rb_include_module

rb_include_module()

rb_include_module
      /* klassにmoduleをインクルードする */
 347  void
 348  rb_include_module(klass, module)
 349      VALUE klass, module;
 350  {
 351      VALUE p, c;
 352      int changed = 0;
 353
 354      rb_frozen_class_p(klass);
 355      if (!OBJ_TAINTED(klass)) {
 356          rb_secure(4);
 357      }
 358
 359      if (NIL_P(module)) return;
 360      if (klass == module) return;
 361
 362      switch (TYPE(module)) {
 363        case T_MODULE:
 364        case T_CLASS:
 365        case T_ICLASS:
 366          break;
 367        default:
 368          Check_Type(module, T_MODULE);
 369      }

(class.c)



rb_include_module
 371      OBJ_INFECT(klass, module);
 372      c = klass;
 373      while (module) {
 374          int superclass_seen = Qfalse;
 375
 376          if (RCLASS(klass)->m_tbl == RCLASS(module)->m_tbl)
 377              rb_raise(rb_eArgError, "cyclic include detected");
 378          /*(A)スーパークラスで既にmoduleをインクルードしていたらスキップ */
 379          for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
 380              switch (BUILTIN_TYPE(p)) {
 381                case T_ICLASS:
 382                  if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
 383                      if (!superclass_seen) {
 384                          c = p;  /* 挿入地点をずらす */
 385                      }
 386                      goto skip;
 387                  }
 388                  break;
 389                case T_CLASS:
 390                  superclass_seen = Qtrue;
 391                  break;
 392              }
 393          }
 394          c = RCLASS(c)->super =
                          include_class_new(module, RCLASS(c)->super);
 395          changed = 1;
 396        skip:
 397          module = RCLASS(module)->super;
 398      }
 399      if (changed) rb_clear_cache();
 400  }

(class.c)

A
c = klass;
while (module) {
    c = RCLASS(c)->super = include_class_new(module, RCLASS(c)->super);
    module = RCLASS(module)->super;
}

modulesupermodulesuper module cons
list = new(item, list)

cc->super module

include_class_new()

include_class_new()


include_class_new()
 319  static VALUE
 320  include_class_new(module, super)
 321      VALUE module, super;
 322  {
 323      NEWOBJ(klass, struct RClass);               /*(A)*/
 324      OBJSETUP(klass, rb_cClass, T_ICLASS);
 325
 326      if (BUILTIN_TYPE(module) == T_ICLASS) {
 327          module = RBASIC(module)->klass;
 328      }
 329      if (!RCLASS(module)->iv_tbl) {
 330          RCLASS(module)->iv_tbl = st_init_numtable();
 331      }
 332      klass->iv_tbl = RCLASS(module)->iv_tbl;     /*(B)*/
 333      klass->m_tbl = RCLASS(module)->m_tbl;
 334      klass->super = super;                       /*(C)*/
 335      if (TYPE(module) == T_ICLASS) {             /*(D)*/
 336          RBASIC(klass)->klass = RBASIC(module)->klass;   /*(D-1)*/
 337      }
 338      else {
 339          RBASIC(klass)->klass = module;                  /*(D-2)*/
 340      }
 341      OBJ_INFECT(klass, module);
 342      OBJ_INFECT(klass, super);
 343
 344      return (VALUE)klass;
 345  }

(class.c)



A

Bmodule

Csuper

module B 11

(symbolic)
11: 

AT_ICLASS include_class_new() ICLASSIinclude

rb_include_module() 12

(include)
12: 

D-2klass D-1 T_ICLASST_ICLASS ruby

basic.klass 使 Ruby


include 13(1)m2 m1c1c1m1 (2)(3)im

(simulate)
13: 

rb_include_module2


rb_include_module()

rb_include_module
 378  /*(A)スーパークラスで既にmoduleをインクルードしていたらスキップ */
 379  for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
 380      switch (BUILTIN_TYPE(p)) {
 381        case T_ICLASS:
 382          if (RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
 383              if (!superclass_seen) {
 384                  c = p;  /* 挿入地点をずらす */
 385              }
 386              goto skip;
 387          }
 388          break;
 389        case T_CLASS:
 390          superclass_seen = Qtrue;
 391          break;
 392      }
 393  }

(class.c)

klasspT_ICLASS module pmodule p->super

p
module M
end
module M2
end
class C
  include M   # まだM2はMにインクルードされてない。
end           # 従ってCのスーパークラスにM2は存在しない。

module M
  include M2  # 今度はMにM2がインクルードされているので、
end
class C
  include M   # ここではM2だけ追加したい
end

include

Module#append_features


 <aamine@loveruby.net>

Ruby  ()

Copyright (c) 2002-2004 Minero Aoki, All rights reserved.