我在doc中找到了Fixnum
的以下功能。
Fixnum
个对象具有直接价值。这意味着当它们作为参数分配或传递时,将传递实际对象,而不是对该对象的引用。
可以在IRB中显示相同的内容吗?希望只有我能正确地理解它?
分配不会为Fixnum对象添加别名。
它究竟是什么呢?
对于任何给定的整数值,实际上只有一个Fixnum对象实例,因此,例如,您不能将单例方法添加到
Fixnum
。
无法理解不使用singleton
对象实例添加Fixnum
方法的原因。
我尝试了第二点如下:
a = 1 # => 1
a.class # => Fixnum
b = a # => 1
b.class # => Fixnum
a == b # => true
a.equal? b # => true
a.object_id == b.object_id # => true
但我仍然感到困惑。任何人都可以帮我在这里了解这些功能的核心吗?
答案 0 :(得分:10)
在Ruby中,大多数对象都需要内存来存储它们的类和实例变量。分配此内存后,Ruby通过此内存位置表示每个对象。将对象分配给变量或传递给函数时,它是传递此内存的位置,而不是此内存中的数据。单身方法利用了这一点。定义单例方法时,Ruby会默默地用新的单例类替换对象类。因为每个对象都存储它的类,所以Ruby可以很容易地用一个实现单例方法的新类替换一个对象的类(并继承自原始类)。
对于具有直接值的对象不再适用:true
,false
,nil
,所有符号以及足够小以适合Fixnum的整数。 Ruby不为这些对象的实例分配内存,它不在内部将对象表示为内存中的位置。相反,它基于其内部表示推断对象的实例。这意味着两个方面:
每个对象的类不再存储在特定位置的内存中,而是由直接对象的类型隐式确定。这就是Fixnums不能使用单例方法的原因。
具有相同状态的直接对象(例如,两个整数2378的Fixnum)实际上是相同的实例。这是因为实例是由这种状态决定的。
为了更好地理解这一点,请考虑在Fixnum上执行以下操作:
>> x = 3 + 7
=> 10
>> x.object_id == 10.object_id
=> true
>> x.object_id == (15-5).object_id
=> true
现在,考虑使用字符串:
>> x = "a" + "b"
=> "ab"
>> x.object_id == "ab".object_id
=> false
>> x.object_id == "Xab"[1...3].object_id
=> false
>> x == "ab"
=> true
>> x == "Xab"[1...3]
=> true
Fixnums的对象id相等的原因是它们是具有相同内部表示的直接对象。另一方面,字符串存在于已分配的内存中。每个字符串的对象id是其对象状态在内存中的位置。
要理解这一点,您必须了解Ruby(至少1.8和1.9)如何在内部处理Fixnums。在Ruby中,所有对象都由C代码中的VALUE
类型的变量表示。 Ruby对VALUE
:
VALUE类型是保存指针的足够大小的最小整数。这意味着,在C中,sizeof(VALUE) == sizeof(void*)
。
任何非直接对象必须在4字节边界上对齐。这意味着Ruby分配的任何对象都会为某个整数4*i
提供地址i
。这也意味着所有指针的两个最低有效位都具有零值。
第一个要求允许Ruby在类型为VALUE
的变量中存储指向对象和立即值的指针。第二个要求允许Ruby根据两个最低有效位检测Fixnum和Symbol对象。
为了使其更具体,请考虑Ruby对象z
的内部二进制表示,我们将在32位体系结构中调用Rz
:
MSB LSB
3 2 1
1098 7654 3210 9876 5432 1098 7654 32 10
XXXX XXXX XXXX XXXX XXXX XXXX XXXX AB CD
Ruby然后解释Rz
的表达式z
,如下所示:
如果D==1
,则z
是Fixnum。此Fixnum的整数值存储在表示的高31位中,并通过执行arithmetic right shift来恢复存储在这些位中的有符号整数来恢复。
测试了三个特殊表示(全部使用D==0
)
Rz==0
,则z
为false
Rz==2
,则z
为true
Rz==4
,则z
为nil
如果ABCD == 1110
,则'z'是符号。通过右移八个最低有效位(即C中的z>>8
)将符号转换成唯一ID。在32位架构上,这允许2 ^ 24个不同的ID(超过1000万)。在64位体系结构上,这允许2 ^ 48个不同的ID。
否则,Rz
表示内存中Ruby对象实例的地址,z
的类型由该位置的类信息确定。
答案 1 :(得分:0)
嗯...
VALUE
。在大多数情况下,VALUE
是指向生活在堆栈上的对象的指针。但是直接值(Fixnums,true,false,nil和其他东西)存在于VALUE
,其中指向对象的指针通常会存在。VALUE
本身,但确实如此。1
,我都使用相同的对象。因此,如果我在1
上定义单例方法,我的程序中的每个位置,所需的程序等都将具有该单例方法。单例方法通常用于局部monkeypatching。所以,为了防止这种情况,Ruby只是不允许你。