`

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模块的过程如下图所示:

include模块,本质上是在对象或者类的klass和super之间插入了一个代理类iclass,这个代理类的方法表(m_table)和变量表 (iv_table)分别指向了被包含的模块的方法表和变量表(通过指针,因此当包含的Module变化的时候,对象或者类也能相应变化),那么在查找类 或者对象的class的时候,上面已经指出将忽略这些代理类。
分享到:
评论
2 楼 lgn21st 2008-04-13  
这张图的出处应该是Ruby Hacking Guide
目前翻译好的中文部分只有第一章,在我看来,解释ruby对象导航图原理上的资料,无出其右...
1 楼 dualface 2008-04-13  
楼主的图用什么软件画的啊?挺不错

相关推荐

    Ruby Hack Guide中文版.chm

    第一部分的内容包括对Ruby语言一个概要介绍和对Ruby对象模型的讲解。从我个人阅读的感觉来看,第一章对于Ruby语言的介绍是一个非常好的起步教程,把Ruby语言中一些核心点都指了出来。比起我读到过一些Ruby语言教程,...

    Ruby常量查找路径问题深入研究

    Ruby 的常量查找路径问题是一直困扰我的一个问题,在工作中遇到过好几次,一直没有彻底弄清楚到底为什么,最近在读一本书《Ruby 元编程》,对 Ruby 对象模型有了更深入的认识,另外读了一篇 blog《Everything you ...

    C#操作Word(word对象模型)

    本文详细介绍了Word对象模型以及如何使用C#开发关于Word的应用程序

    Ruby-Reform能够给你一个Form对象模型包含验证和嵌套设置

    Reform - 能够给你一个Form对象模型包含验证和嵌套设置,框架和数据库无关。

    jazz_model:Jazz模型-爵士理论和其他很酷的东西的数据模型

    Jazz Toolbox的核心是一个完整的Ruby对象模型,代表了Jazz理论的概念,这些模型被提炼为最基本的概念并以非常抽象的方式进行了架构。 该系统以数据为中心,理论上所有“规则”(例如,C7和弦中的音调)都独立包含在...

    timeasure:Ruby中用于概要分析的透明方法级包装器

    量测 它是什么? Timeasure是用于概要分析目的的透明方法级包装器。...Timeasure对跟踪的模块和类在Ruby对象模型中使用的干预最少。 它与Rails和非Rails应用程序很好地集成在一起。 Timeasure的灵感来自的和H

    C#操作Excel(Excel对象模型)_v1.0

    Excel对象模型中文版。若要使用C#语言进行Excel操作,必须首先了解Excel的对象模型。本文用很多实例代码详细的介绍了Excel的对象模型

    ruby教程.rar

    对象 类 执行 结束时的相关处理 线程 安全模型 正则表达式 Ruby的语法 字句构造 程序 变量和常数 字面值 操作符表达式 控制结构/异常处理 方法调用 类/方法的定义 标准库 内部函数 内部变量 ...

    sinatra-fix_951:Sinatra 问题 951 的修复(未定义方法`join' for #

    修复 Sinatra 1.4.5 的 请注意,这对于 1.4.6+ 来说是不必要的,因为... 如果您想了解为什么这可以解决问题,那么您需要学习 Ruby 对象模型。 这是在、来和我们一起学习的!安装如果您使用 Bundler,请将其添加到您的

    Ruby学习笔记

    对象模型比起JavaScript好的不是一点两点,clone关键字真是为原型式编程量身打造的,new就显得不伦不类了,尤其是我从Java开始的。恩,废话就少提,下面我学习Ruby的各个部分。其中Ruby风格这一部分是开放的,因为我...

    Spreadsheet Architect是一个库,可让您轻松地从ActiveRecord关系,纯Ruby对象或表格数据中创建XLSX,ODS或CSV电子表格。-Ruby开发

    主要功能:带有自定义数据的简单的简单自定义电子表格数据源:来自Array,ActiveRecord关系或纯Ruby对象实例数组的表格数据轻松设置电子表格的样式和自定义创建多页电子表格设置类/模型或项目特定的默认值对我们来说...

    Selenium-Ruby-Template:具有页面对象模型的Selenium Ruby单元测试模板

    具有页面对象模型的Selenium Ruby单元测试模板 要在运行时自动执行二进制文件管理,请使用 ,这是的优秀库 如何使用? 在lib / pageobjects包下创建Web应用程序的Page Objects,在测试包下的测试中调用这些Page ...

    在Ruby(和Rails)中部署机器学习模型-Ruby开发

    在Ruby(和Rails)中部署机器学习模型Trove:fire:在Ruby(和Rails)中部署机器学习模型与XGBoost,Torch.rb,fastText和许多其他gems配合使用非常好。将这一行添加到应用程序的Gemfile中:gem'trove'并运行:bundle ...

    dm-validations:用于对 DM 模型和纯 Ruby 对象执行验证的库

    这是一个 DataMapper 插件,为 DataMapper 模型类提供验证。 安装 当您在应用程序中需要 dm-validations' 时,DataMapper 验证功能可自动用于 DataMapper 资源。 无需手动包含任何内容,一旦需要此 gem,每个 ...

    JSON对象展示生成模板boxer-ruby.zip

    boxer 是一款简单的用户自定义模板,用来生成 JSON 对象模型表示。 标签:boxer

    redis-objects:将Redis类型直接映射到Ruby对象

    Redis :: Objects-将Redis类型直接映射到Ruby对象 这不是ORM。 在Redis周围包装ORM的人们都没有抓住重点。 Redis的杀手级功能是它允许您对单个数据结构(例如计数器,列表和集合)执行原子操作。 原子部分是巨大的...

    active_type:使任何Ruby对象像ActiveRecord一样发出嘎嘎声

    使任何Ruby对象像ActiveRecord一样发出嘎嘎声 ActiveType是我们在Rails中对“演示者模型”(或“表单模型”)的理解。 我们希望控制器(和表单)与不由数据库表支持的模型对话,或者具有不应与应用程序其余部分共享...

    Ruby on Rails Web开发之旅.pdf【第二部分】

     3.3.2 与Ruby对象交互  3.3.3 Ruby中的标点  3.4 在Ruby中使用面向对象编程  3.4.1 类和对象  3.4.2 对象层功能  3.4.3 类层功能  3.4.4 继承  3.4.5 返回值  3.5 标准输出  3.6 Ruby核心类  ...

    Ruby on Rails Web开发之旅.pdf【第一部分】

     3.3.2 与Ruby对象交互  3.3.3 Ruby中的标点  3.4 在Ruby中使用面向对象编程  3.4.1 类和对象  3.4.2 对象层功能  3.4.3 类层功能  3.4.4 继承  3.4.5 返回值  3.5 标准输出  3.6 Ruby核心类  ...

Global site tag (gtag.js) - Google Analytics