Ruby的对象模型

  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
end
OtherClass.name='1'
p OtherClass.name
OtherClass.test

    图中的instance是OtherClass的一个实例,那么显然instance的class是OtherClass,可是图中的(instance)又是什么呢?(instance)就是对象的singleton类,singleton类这个名称怪怪的,不过每个对象只能有一个singleton类的角度上说也可以理解。看看下面的例子:

class OtherClass
end
instance=OtherClass.new
class<<instance
  def test
    p "a.test"
  end
  attr_accessor:name
end
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);

(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

时间: 2024-10-06 12:06:41

Ruby的对象模型的相关文章

《Ruby程序员修炼之道》(第2版)目录—导读

版权 Ruby程序员修炼之道(第2版) • 著 [美] David A. Black 译 钟凤鸣 陈雪静 责任编辑 杨海玲 • 人民邮电出版社出版发行 北京市丰台区成寿寺路11号 邮编 100164 电子邮件 315@ptpress.com.cn 网址 http://www.ptpress.com.cn • 读者服务热线:(010)81055410 反盗版热线:(010)81055315 版权声明 Original English language edition, entitled The W

《Effective Ruby:改善Ruby程序的48条建议》一第6条:了解Ruby如何构建继承体系

第6条:了解Ruby如何构建继承体系 问题:当你向一个对象发送消息时,你知道Ruby是怎么定位到那个正确的方法的吗?答案看上去很简单:使用继承体系.之所以说答案是看上去简单,因为Ruby构建继承体系是在幕后进行的.这是Ruby用自己的方式来隐藏真正发生的事情的罕见情形之一,它常常带来不必要的困惑.Ruby提供给我们的用来发现继承关系中的类的方法并能完全解释其本质.还好,Ruby解释器在内部构建的继承体系是一致而简单的,只要你明白一些它的技巧. 探索Ruby查询方法的机制将揭开语言实现方式的面纱,

Ruby 元编程:第一部分

元编程就是编写能为你编写代码的代码.但那不就是代码生成器所做的事情吗,就像是 rails gem,或者 yeoman?或者甚至是字节码编译器? 是的,但元编程一般指的是 Ruby 中的另外一些东西.ruby 中的元编程指的是能为你动态地编写代码的代码.是在运行时发生的.Ruby 是动态元编程的首要语言,因为它采用了 类型推断 并且是强 发射的 – 相比现有的其它语言处在一个更高的级别.这能让你做一些像使用几行代码就可以加入大量功能这样事情,真的很酷,但是有一个问题:一个不小心,在你提升很多东西的

Ruby 1.9概要(3)类和模块

三.类和模块 1.Module#instance_methods, #private_instance_methods, #public_instance_methods Module这三个方法都将返回方法名 的symbol组成的数组,而非过去的字符串数组. 2.Module#const_defined?, #const_get 这两个方法都添加一个参数flag,用来决定是否将它的ancestor中的const包括在查 找链中,例如: module A; X = 1; def foo; end 

《Effective Ruby:改善Ruby程序的48条建议》一第2章 类、对象和模块

第2章 类.对象和模块面向对象程序设计(OOP)是Ruby的谋生之道.Ruby通常被认为是一门纯粹的面向对象语言,因为Ruby中的任何事物都是或者可以被转化为一个对象,我是说每个事物.Ruby的对象模型受到Smalltalk的严重影响,因此,如果你是由C++或Java转型而来的程序员,可能会觉得这和你曾使用过的其他语言有些不同.类也是对象这个事实足以让你的思维陷入无限递归模式.此外还有一些陷阱,如子类不会自动初始化其超类,以及定义变量和调用setter方法存在模糊的概念.本章将针对这些问题进行整

得到singleton类?

在Ruby中,无论类或者对象,都有一个singlton类(或者称为metaclass),有兴趣的话读读过去写的这篇<Ruby的对象模型>.当我们获取某个类或者对象的class属性时,其实会忽略c ruby层次上的singleton类,那么我们如何得到singleton类呢?比较有趣的做法: singletonclass=class<<Test;self;end 对于对象,也是如此: test=Test.new metaclass=class<<test;self;end

Ruby对象模型总结

参考<Ruby元编程>,元编程,即 用来编写代码的代码 . 对象由一组实例变量和一个类的引用组成 对象的方法存在与对象所属的类中,类似js中的prototype,在ruby中准确的说,应该是实例方法 类本身是Class类的队形,类的名字不过是常量而已 Class类是Module的子类,模块基本上是由一组方法组成的包.类除了具有模块的特性,还可以被实例化,组织为层次结构 常量像文件系统,按照树形结构组织 每个类都有一个祖先链,这个链从自己所属的类开始,向上知道BasicObject类结束 当调用

Halloway:对Ruby VS Java误区的深度剖析

Relevance咨询公司的Stuart Halloway最近编写了一个关于"Ruby vs. Java之怪谈"的系列博客文章.这个系列文章的灵感,源自他最近从一个从零起步.没有先前约束的Ruby项目转回一个成熟完备的Java项目后的心得体会.在这个历时多日的项目过程中,Halloway对以下几个"误区"进行了探索: 误区之一:Ruby适合小型项目,而Java更适用于大型的.复杂的项目. 概括起来,Halloway主张,对于小型项目来说,诸如未知因素一类的问题可能会

Ruby元编程的白魔法书

在Ruby的世界中,程序员们享受着各种光怪陆离的语法糖,也经历着各种各样的陷阱.而这一切的根本就在于Ruby强大 的元编程能力.元编程就像Ruby世界的魔法,当其是白魔法的时候可以帮助你把程序变得异常简洁,美观:而当其是黑魔法 的时候,你将会迷失在一些很难解释的Bug中. <Ruby元编程>就是一部告诉大家如何使用,控制Ruby元编程魔法的 秘籍.该书的写作手法非常值得称道,作者把所有的知识点浓缩在了一个星期的工作过程中,通过一个菜鸟和大牛针对项目 中遇到的各种问题的讨论,解决来引入各种元编程