instance通过OtherClass.new创建,但是此时(instance)还不存在,这与(OtherClass)情况不同,每个类一经创建就有一个metaclass,而对象就不一样,只有当你通过class<<instance 语法创建的时候,(instance)才被创建。注意test方法和name变量都将是instance对象特有的,类OtherClass并没有改变。观察下,发现(instance)继承于OtherClass,引出类的metaclass与对象的singleton类的又一个区别:类的metaclass继承自父类的metaclass,而对象的singleton类则是继承于对象的class。 那么当我们调用instance.class的时候,怎么不返回(instance)?这是c ruby在底层做了处理,instance的class在c ruby层次是(instance),当查找的时候忽略了singleton类以及下面将要谈到的include模块的代理类,沿着继承链上查找: 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) 核心代码就是: while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) { cl = RCLASS(cl)->super; } 其中FL_TEST(cl,FL_SINGLETON)用于测试是否是singleton类,而TYPE(cl)==TL_ICLASS是否是包含模块的代理类,TL_ICLASS的I就是include的意思。 图中类OtherClass继承Object,这个是显而易见的,不再多说。而Object、Class和Module这三个类是没办法通过API创建的,称为元类,他们的之间的关系如图所示,Object的class是Class,Module继承Object,而Class又继承Module,因此Class.kind_of? Object返回true,这个问题类似先有鸡,还是先有蛋的问题,是先有Object?还是先有Class?而c ruby的解决办法是不管谁先有,创建Object开始,接着创建Module和Class,然后分别创建它们的metaclass,从此整个Ruby的对象模型开始运转。 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) 那么当我们调用Class.class发生了什么?Class的klass其实指向的是(Class),可根据上面的代码,我们知道会忽略这个(Class),继续往上找就是(Module),同理找到(Object),而(Object)继承自Class,显然Class的类仍然是Class,Class的类的类也是Class,多么有趣。同理,Object.class和Module.class都将是Class类。 再来看看include模块时发生的故事。include模块的过程如下图所示: include模块,本质上是在对象或者类的klass和super之间插入了一个代理类iclass,这个代理类的方法表(m_table)和变量表(iv_table)分别指向了被包含的模块的方法表和变量表(通过指针,因此当包含的Module变化的时候,对象或者类也能相应变化),那么在查找类或者对象的class的时候,上面已经说明将忽略这些代理类。
文章转自庄周梦蝶 ,原文发布时间2007-09-29
相关资源:敏捷开发V1.0.pptx