`
winteen
  • 浏览: 13036 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[RubyHackingGuide]统一处理对象之VALUE

    博客分类:
  • Ruby
阅读更多
VALUE是Ruby的C实现中用来"指向/引用/代表"所有Ruby对象的"指针"的统一的类型

通过统一类型,可以获得类似"多态"的好处,ruby实现起来就更为简洁(代码方面).
然后, 同样是出于实现的考虑(性能方面), VALUE并不全是指针:
   1. 小的整数
   2. 符号
   3. true
   4. false
   5. nil
   6. Qundef
以上六位就是所谓的"内嵌对象"(VALUE并不是内存地址,其代表的对象是内嵌在VALUE的数值中).

小整数的内嵌规则是:
#define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))  
#define FIXNUM_FLAG 0x01 

数值乘以2再加1(奇数).

符号的内嵌规则是:
#define SYMBOL_FLAG 0x0e  
#define ID2SYM(x) ((VALUE)(((long)(x))<<8|SYMBOL_FLAG)) 

数值乘以256再加14(不能被4整除的偶数)
看到这里,大家可能会疑惑,小整数的数值是本身,但符号(Symbol)的数值又是什么呢?
简单来说,每个ruby进程中维护了一个字符串和数值一一对应的hash表,
因此就可以使用数值来代表(Identify)字符串所表示的"名字", 减少了内存和字符串比较的开销.
static NODE*  
search_method(klass, id, origin)  
      VALUE klass, *origin;  
      ID id;  
{  
      NODE *body;  
  
      if (!klass) return 0;  
      while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {  
          klass = RCLASS(klass)->super;  
          if (!klass) return 0;  
      }  
  
      if (origin) *origin = klass;  
      return body;  
}  

例如这个search_method就是在klass类中搜索名称的ID为id的方法, 并将方法的"出处"(定义方法的类)保存在orgin中.
Ruby为"数值"的"特殊使用"(用做'名字'的ID)单独创建了一个类型:符号(Symbol).

3-6的内嵌规则是:
#define Qfalse 0        /* Ruby's false */  
#define Qtrue  2        /* Ruby's true */  
#define Qnil   4        /* Ruby's nil */ 
#define Qundef 6        /* undefined value for placeholder */  


除了内嵌对象外, VALUE的值便是Ruby对象对应的C结构体的内存地址.
C结构体的内存通常不是从第一个块(0-?)开始分配的,因此不会和Qfalse,Qnil冲突.
且所有Ruby对象的C结构体的共同特征是,其内存地址一定是4的倍数(还记得C中Struct对齐么?).
因此,仅凭VALUE的数值就可以区分它是小整数,符号,Q值,还是内存地址(有例外!).

switch (TYPE(obj)) {  
      /* (A) */  
        case T_OBJECT:  
        case T_CLASS:  
        case T_MODULE:  
          if (ROBJECT(obj)->iv_tbl &&  
                  st_lookup(ROBJECT(obj)->iv_tbl, id, &val))  
              return val;  
          break;  
      /* (B) */  
        default:  
          if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj))  
              return generic_ivar_get(obj, id);  
          break;  
      } 

看到代码中的TYPE宏么, 就是根据VALUE的数值返回obj可能指向的结构体的类型.
例如,一个RString类型的结构体实例的TYPE就是T_STRING. 那么TYPE(2)会返回T_FIXNUM么?
错! 应返回T_TRUE?(如果有...), 而TYPE(3)则返回T_FIXNUM.

TYPE宏可以区分内嵌对象和对象,那么,它是如何区分不同的对象的呢?此时,VALUE的值都是内存地址, 不同的是它所指向的结构体.正如你想的那样, TYPE宏在运行时区分结构体类型的能力正是来源于结构体本身,换句话说,结构体存储了自身的类型信息.关于这些结构体,详见 Ruby的对象类.
  • 大小: 6.5 KB
分享到:
评论

相关推荐

    js获取对象,数组所有属性键值(key)和对应值(value)的方法示例

    在JavaScript编程中,获取对象和数组的属性键值(key)和对应值(value)是一项基本操作。本文将详细介绍如何实现这一功能,并提供相应的代码示例。 首先,我们需要理解JavaScript中的对象和数组。对象是一种键值对...

    SpringBoot接口加密解密统一处理

    在本文中,我们将深入探讨如何在SpringBoot中实现接口的加密解密统一处理,以及如何通过自定义注解来灵活控制加密解密的执行。 首先,我们创建两个自定义注解,`DecryptRequest`和`EncryptResponse`,用于标识哪些...

    JS递归遍历对象获得Value值方法技巧

    递归遍历对象时,我们通常需要处理对象的嵌套层级,并且每个层级都可能包含不同的数据类型。为了能够全面地获取到所有的值,递归函数需要能够识别和处理各种不同的数据类型,包括嵌套的对象、数组、字符串、数字等。...

    get-js-object-key-value:获取一个JS对象的key和value

    getKeyValue(对象: JSObject ) JSObject可以是具有一个或多个属性的对象 返回 一个属性应该返回一个带有{key, value}的js 对象 多个属性应该返回一个包含[{key, value}, {key, value}]的数组 undefined以防传递...

    java使用fastJson处理复杂Json字符串,直接获取key对应的value值

    java使用fastJson处理复杂Json字符串,直接获取key对应的value值

    jquery获取当前点击对象的value方法

    例:获取ul中li的value值 首先,在html中我们要为每个li设置value值 代码如下: &lt;ul&gt; &lt;li value=”你好”&gt;&lt;/li&gt; &lt;li value=”hello”&gt;&lt;/li&gt; &lt;li value=”&gt;&lt;/li&gt; &lt;/ul&gt; 再通过jquery根据点击事件获取对应的value 代码...

    Unity UGUI控件 OnValueChanged事件测试说明Demo

    4. **事件处理**:在Unity中,你可以通过两种方式处理OnValueChanged事件:一是使用Unity的EventSystem和IPointerClickHandler接口,另一种是使用C#脚本直接挂接OnValueChanged事件。后一种方法通常更直观,只需在...

    面向对象编程基础_python面向对象_python教程_

    在Python中,面向对象编程是其核心特性之一,使得Python成为了一种非常适合进行复杂系统开发的语言。下面我们将深入探讨Python中的面向对象编程基础。 一、类与对象 1. **类(Class)**:类是面向对象编程的基础,...

    使用递归遍历对象获得value值的实现方法

    一般要用到递归,就要判断对象是否和父类型是否一样 这里演示简单的对象递归,还有数组递归类似。 var obj = { a:{w:1,y:2,x:3}, b:{s:4,j:5,x:6}, ...以上这篇使用递归遍历对象获得value值的实现方法

    JavaScript更改原始对象valueOf的方法

    默认情况下,当一个对象被当作原始值(如字符串、数字)处理时,JavaScript会调用该对象的`valueOf`方法来获取这个基本值。这个过程发生在隐式类型转换时,比如在比较操作、算术运算或者作为字符串连接的一部分时。 ...

    前端开源库-value-pipe

    3. **错误处理**:如果在管道中某个函数抛出错误,`value-pipe`会捕获并返回一个错误对象,这可以帮助你在处理过程中处理异常情况。 4. **自定义管道**:你可以根据需求创建自己的管道类,扩展`value-pipe`的功能,...

    Laravel开发-laravel-value-objects

    8. **接口一致性**:通过定义统一的接口,值对象可以使客户端代码更加简洁,因为它们总是知道如何处理值对象,而无需关心具体的实现细节。 9. **单元测试**:值对象的定义清晰,有助于编写针对性的单元测试,确保其...

    android Spinner value值与text值

    在Android开发中,Spinner是一个非常常见...理解如何设置和处理Spinner的选中事件,以及如何获取选中项的text和value,是Android开发中必备的技能之一。通过实践上述步骤和参考示例代码,你应该能够熟练掌握这一功能。

    Grafana 变量 KeyValue 形式实现.md

    Grafna Dashboard 中,支持 `variables` 变量, 以下拉列表的形式展示在左上角,用户可选择其内容,下面的 Panel 中的对象查询中增加 $xxx 即可实现对象的切换, 比较方便。 问题: 常规实现没有问题,但对于下拉列表...

    value stack

    - **动态数据模型**:栈中可以包含多个对象,这使得Value Stack能够处理复杂的业务场景,例如,同时处理多个Action对象或共享数据。 - **灵活性**:OGNL支持表达式计算,不仅可以访问属性,还能调用方法,甚至执行...

    auto-value-firebase, 创建Firebase数据库对象的AutoValue扩展.zip

    auto-value-firebase, 创建Firebase数据库对象的AutoValue扩展 AutoValue: Firebase扩展对于与 Firebase实时数据库兼容的值类,必须:包含 public"获取"-prefixed访问器或者 public 字段,以及包含一个空的或者...

    Android-使用Kotlin属性委托实现的基于文件的Key-Value持久化工具

    当我们定义一个属性时,可以使用`by`关键字来指定一个委托对象,该对象将负责处理属性的读写操作。 在基于文件的Key-Value存储中,我们通常会用到文件的读写操作。Android提供了`java.io.File`类来处理文件操作,但...

Global site tag (gtag.js) - Google Analytics