Ruby的对象模型

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


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

ruby 代码
 
  1. class OtherClass  
  2. end  
  3. instance=OtherClass.new  
  4. class <<  instance <instance><instance></instance></instance>
  5.   def test  
  6.     p "a.test"  
  7.   end  
  8.   attr_accessor:name  
  9. end  
  10. instance.test =>"a.test"  
  11. instance.name="dennis"  
  12. instance.name  =>"dennis"  

     instance通过OtherClass.new创建,但是此时(instance)还不存在,这与(OtherClass)情况不同,每个类一经创建 就有一个metaclass,而对象就不一样,只有当你通过class << instance 语法(或者def instance.test等等)创建的时候,(instance)才被创建。注意test方法和name变量都将是instance对象特有的,类OtherClass并没有改变。 观察下,发现(instance)继承于OtherClass,引出类的metaclass与对象的singleton类的又一个区别:类的 metaclass继承自父类的metaclass,而对象的singleton类则是继承于对象的class。<instance>
    那么当我们调用instance.class的时候,怎么不返回(instance)?这是c ruby在底层做了处理,instance的class在c ruby层次是(instance),当查找的时候忽略了singleton类以及下面将要谈到的include模块的代理类,沿着继承链上查找:

</instance>
cpp 代码
 
  1. 86 VALUE  
  2. 87 rb_obj_class(obj)  
  3. 88 VALUE obj;  
  4. 89 {  
  5. 90 return rb_class_real(CLASS_OF(obj));  
  6. 91 }  
  7.   
  8. 76 VALUE  
  9. 77 rb_class_real(cl)  
  10. 78 VALUE cl;  
  11. 79 {  
  12. 80 while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {  
  13. 81 cl = RCLASS(cl)->super;  
  14. 82 }  
  15. 83 return cl;  
  16. 84 }  
  17.   
  18. (object.c)  

核心代码就是:
cpp 代码
 
  1. while (FL_TEST(cl, FL_SINGLETON) || TYPE(cl) == T_ICLASS) {  
  2.   cl = RCLASS(cl)->super;  
  3.  }  

    其中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是Class类,而Class类又是Object的子类,这个问题类似先有鸡,还是先有蛋的问题,是先有Object?还是先有Class?而c ruby的解决办法是不管谁先有,创建Object开始,接着创建Module和Class,然后分别创建它们的metaclass,从此整个Ruby的 对象模型开始运转。
cpp 代码
 
  1. 1243 rb_cObject = boot_defclass("Object", 0);  
  2. 1244 rb_cModule = boot_defclass("Module", rb_cObject);  
  3. 1245 rb_cClass = boot_defclass("Class", rb_cModule);  
  4. 1246  
  5. 1247 metaclass = rb_make_metaclass(rb_cObject, rb_cClass);  
  6. 1248 metaclass = rb_make_metaclass(rb_cModule, metaclass);  
  7. 1249 metaclass = rb_make_metaclass(rb_cClass, metaclass);  
  8.   
  9. (object.c)  

那么当我们调用Class.class发生了什么?Class的klass其实指向的是(Class),可根据上面的代码,我们知道会忽略这个 (Class),继续往上找就是(Module),同理找到(Object),而(Object)继承自Class,显然Class的类仍然是 Class,Class的类的类也是Class,无穷递归下去,多么有趣。同理,Object.class和Module.class都将是Class类。

    再来看看include模块时发生的故事。include模块的过程如下图所示:
Ruby的对象模型
include模块,本质上是在对象或者类的klass和super之间插入了一个代理类iclass,这个代理类的方法表(m_table)和变量表 (iv_table)分别指向了被包含的模块的方法表和变量表(通过指针,因此当包含的Module变化的时候,对象或者类也能相应变化),那么在查找类 或者对象的class的时候,上面已经指出将忽略这些代理类。

你可能感兴趣的:(C++,c,软件测试,C#,Ruby)