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

目录
相关文章
|
开发者 测试技术 Android开发
Xamarin 开发者的五大常见问题及解决方案:从环境搭建到性能优化,全面解析高效跨平台应用开发的技巧与代码实例
【8月更文挑战第31天】Xamarin 开发者常遇问题及解决方案覆盖环境搭建至应用发布全流程,助新手克服技术难关。首先需正确安装配置 Visual Studio 及 Xamarin 支持,设置 iOS/Android 测试环境。利用 Xamarin.Forms 和 XAML 实现高效跨平台开发,共享 UI 和业务逻辑代码。针对性能优化,采取减少 UI 更新、缓存计算结果等措施,复杂问题则借助 Xamarin Profiler 分析。
236 0
|
设计模式 缓存 测试技术
Ruby代理模式之谜:如何用简单的方法创建灵活的对象接口?
【8月更文挑战第31天】代理模式是一种设计模式,通过创建代理对象来控制对目标对象的访问,可在Ruby中通过Proc对象、模块混入等方式实现。本文介绍了代理模式的概念及其实现方法,并提供了缓存、验证和日志代理等应用场景的示例代码,帮助开发者更好地理解和运用这一模式,提升程序灵活性与健壮性。
133 0
Ruby Programming | 连载 07 - Ruby 对象的原生行为
Ruby Programming | 连载 07 - Ruby 对象的原生行为
Ruby Programming | 连载 07 - Ruby 对象的原生行为
|
存储 IDE 开发工具
Ruby Programming | 连载 03 - Ruby 对象基础
Ruby Programming | 连载 03 - Ruby 对象基础
Ruby Programming | 连载 03 - Ruby 对象基础
|
定位技术 API 图形学
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)
528 0
【Unity开发实战】—— 2D项目1 - Ruby‘s Adventure 游戏世界中各个对象的交互(3-1)