ruby三日游之后(一)——Ruby对象的一次探索

来源:互联网 发布:海龙设计软件多少钱 编辑:程序博客网 时间:2024/05/02 08:12


ruby三日ruby对象

目录(?)[+]

来自Ruby世界似乎是这样说的,“Ruby内一切都是对象”。

有趣的一切都是对象,那么一切也就没有不再是对象了?

"面向对象的设计方法是在结构化编程对控制流程实现了结构化后,又加上了对数据的结构化。"——《松本行弘的程序世界》

这里引用自《Ruby Hacking Guide》的对象一章的说法,对象存在的必要条件

  1. 能够区分自身与其它(拥有标识)
  2. 能够响应请求(方法)
  3. 保持内部状态(实例变量)

Ruby 中的类层次结构


然后我们再看看一个有意思的结果:
[ruby] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. irb(main):022:0> Object.class  
  2. => Class  
  3. irb(main):023:0> Object.superclass  
  4. => BasicObject  
  5. irb(main):024:0> BasicObject.superclass  
  6. => nil  
  7. irb(main):025:0>   

这里使用的是1.9.3版本的ruby,于是这是Ruby的类层次结构,至于为什么是这样的,不凡看看下面的这些代码。
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. void  
  2. Init_class_hierarchy(void)  
  3. {  
  4.     rb_cBasicObject = boot_defclass("BasicObject", 0);  
  5.     rb_cObject = boot_defclass("Object", rb_cBasicObject);  
  6.     rb_cModule = boot_defclass("Module", rb_cObject);  
  7.     rb_cClass =  boot_defclass("Class",  rb_cModule);  
  8.   
  9.     rb_const_set(rb_cObject, rb_intern("BasicObject"), rb_cBasicObject);  
  10.     RBASIC_SET_CLASS(rb_cClass, rb_cClass);  
  11.     RBASIC_SET_CLASS(rb_cModule, rb_cClass);  
  12.     RBASIC_SET_CLASS(rb_cObject, rb_cClass);  
  13.     RBASIC_SET_CLASS(rb_cBasicObject, rb_cClass);  
  14. }  

这是用于初化化类层次的代码,也就是hierarchy的意思,层次,层次结构。
至于,boot_defclass那么就看看下面的
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. static VALUE  
  2. boot_defclass(const char *name, VALUE super)  
  3. {  
  4.     VALUE obj = rb_class_boot(super);  
  5.     ID id = rb_intern(name);  
  6.   
  7.     rb_name_class(obj, id);  
  8.     rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);  
  9.     return obj;  
  10. }  

如果这里还有什么令人不明白的地方,那么可能就是VALUE了。
原文是这么长:
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #if defined HAVE_UINTPTR_T && 0  
  2. typedef uintptr_t VALUE;  
  3. typedef uintptr_t ID;  
  4. # define SIGNED_VALUE intptr_t  
  5. # define SIZEOF_VALUE SIZEOF_UINTPTR_T  
  6. # undef PRI_VALUE_PREFIX  
  7. #elif SIZEOF_LONG == SIZEOF_VOIDP  
  8. typedef unsigned long VALUE;  
  9. typedef unsigned long ID;  
  10. # define SIGNED_VALUE long  
  11. # define SIZEOF_VALUE SIZEOF_LONG  
  12. # define PRI_VALUE_PREFIX "l"  
  13. #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP  
  14. typedef unsigned LONG_LONG VALUE;  
  15. typedef unsigned LONG_LONG ID;  
  16. # define SIGNED_VALUE LONG_LONG  
  17. # define LONG_LONG_VALUE 1  
  18. # define SIZEOF_VALUE SIZEOF_LONG_LONG  
  19. # define PRI_VALUE_PREFIX PRI_LL_PREFIX  
  20. #else  
  21. # error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----  
  22. #endif  


那么,简化一下为和前几个版本一致的,那么就是
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. typedef unsigned long VALUE;  
原本的模型应该是这样的

Ruby的对象变的

让我们再简单看一看一个示例
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. irb(main):025:0> 1.class  
  2. => Fixnum  
  3. irb(main):026:0> Fixnum.class  
  4. => Class  
  5. irb(main):027:0> Fixnum.superclass  
  6. => Integer  
  7. irb(main):028:0> Fixnum.superclass.superclass  
  8. => Numeric  
  9. irb(main):029:0> Fixnum.superclass.superclass.superclass  
  10. => Object  
  11. irb(main):030:0> Fixnum.superclass.superclass.superclass.superclass  
  12. => BasicObject  
  13. irb(main):031:0>   
好吧,我觉得引用RHG中的图来说明可能会更简单一点,只是这张图只能做一时只用(转载保留 Phodal's Blog Phodal's  zenthink

因为这些都已经改变了
原先的对象只有这些
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #define R_CAST(st)   (struct st*)  
  2. #define RBASIC(obj)  (R_CAST(RBasic)(obj))  
  3. #define ROBJECT(obj) (R_CAST(RObject)(obj))  
  4. #define RCLASS(obj)  (R_CAST(RClass)(obj))  
  5. #define RMODULE(obj) RCLASS(obj)  
  6. #define RFLOAT(obj)  (R_CAST(RFloat)(obj))  
  7. #define RSTRING(obj) (R_CAST(RString)(obj))  
  8. #define RREGEXP(obj) (R_CAST(RRegexp)(obj))  
  9. #define RARRAY(obj)  (R_CAST(RArray)(obj))  
  10. #define RHASH(obj)   (R_CAST(RHash)(obj))  
  11. #define RDATA(obj)   (R_CAST(RData)(obj))  
  12. #define RSTRUCT(obj) (R_CAST(RStruct)(obj))  
  13. #define RBIGNUM(obj) (R_CAST(RBignum)(obj))  
  14. #define RFILE(obj)   (R_CAST(RFile)(obj))  
可是现在呢?
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #define R_CAST(st)   (struct st*)  
  2. #define RBASIC(obj)  (R_CAST(RBasic)(obj))  
  3. #define ROBJECT(obj) (R_CAST(RObject)(obj))  
  4. #define RCLASS(obj)  (R_CAST(RClass)(obj))  
  5. #define RMODULE(obj) RCLASS(obj)  
  6. #define RFLOAT(obj)  (R_CAST(RFloat)(obj))  
  7. #define RSTRING(obj) (R_CAST(RString)(obj))  
  8. #define RREGEXP(obj) (R_CAST(RRegexp)(obj))  
  9. #define RARRAY(obj)  (R_CAST(RArray)(obj))  
  10. #define RHASH(obj)   (R_CAST(RHash)(obj))  
  11. #define RDATA(obj)   (R_CAST(RData)(obj))  
  12. #define RTYPEDDATA(obj)   (R_CAST(RTypedData)(obj))  
  13. #define RSTRUCT(obj) (R_CAST(RStruct)(obj))  
  14. #define RBIGNUM(obj) (R_CAST(RBignum)(obj))  
  15. #define RFILE(obj)   (R_CAST(RFile)(obj))  
  16. #define RRATIONAL(obj) (R_CAST(RRational)(obj))  
  17. #define RCOMPLEX(obj) (R_CAST(RComplex)(obj))  
比之前多了TYPEDATA,RATIONAL,COMPLEX三个对象


Ruby 不变的对象

让我们看看结构化的那部分

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. struct RBasic {  
  2.     VALUE flags;  
  3.     const VALUE klass;  
  4. }  

以及Object


[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. struct RObject {  
  2.     struct RBasic basic;  
  3.     union {  
  4.     struct {  
  5.         long numiv;  
  6.         VALUE *ivptr;  
  7.             struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */  
  8.     } heap;  
  9.     VALUE ary[ROBJECT_EMBED_LEN_MAX];  
  10.     } as;  
  11. };  


还有Rstring

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. struct RString {  
  2.     struct RBasic basic;  
  3.     union {  
  4.     struct {  
  5.         long len;  
  6.         char *ptr;  
  7.         union {  
  8.         long capa;  
  9.         VALUE shared;  
  10.         } aux;  
  11.     } heap;  
  12.     char ary[RSTRING_EMBED_LEN_MAX + 1];  
  13.     } as;  
  14. };  

于是让我们回到

对象存在的必要条件

  1. 能够区分自身与其它(拥有标识)
  2. 能够响应请求(方法)
  3. 保持内部状态(实例变量)

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. struct RBasic {  
  2.     VALUE flags;  
  3.     const VALUE klass;  
  4. }  
这两部分。
  • flags是个多目的的标记,大多用以记录结构体的类型。
  • klass包含了这个对象归属的类。
最后,让我们看看Float是怎么说的
[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. struct RFloat {  
  2.     struct RBasic basic;  
  3.     double float_value;  
  4. }; 
原创粉丝点击