ruby的对象模型,包含在下面这张图中:

首先要知道,ruby中的类也是对象,类相比于其他对象特殊的地方在于能够产生对象,既然类是对象,那么它显然也有类,也就是所谓类的类,这个类的类在ruby中就是类的metaclass,图中的(otherclass),(otherclass)就是类otherclass的klass(c层次),(otherclass)存储了类的方法(类方法)和类的实例变量,并且是唯一的且不可实例化。在ruby层次上我们想操作(otherclass)应该类似:
class otherclass
end
class<<otherclass
attr_accessor:name #name是otherclass的实例变量
def test
p 'hello'
end
otherclass.name='1'
p otherclass.name
otherclass.test
图中的instance是otherclass的一个实例,那么显然instance的class是otherclass,可是图中的(instance)又是什么呢?(instance)就是对象的singleton类,singleton类这个名称怪怪的,不过每个对象只能有一个singleton类的角度上说也可以理解。看看下面的例子:
instance=otherclass.new
class<<instance
p "a.test"
attr_accessor:name
instance.test
instance.name="dennis"
p instance.name
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);
那么当我们调用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