Ruby对象to_s对象id的编码是什么?
Ruby object to_s what is the encoding of the object id?
在 Ruby 中,对象的 to_s
包括对象 ID 的编码。
[2] pry(main)> shape = Shape.new(4,4)
=> #<Shape:0x00007fac5eb6afc8 @num_sides=4, @side_length=4>
文档中说
Returns a string representing obj. The default to_s prints the object’s class and an encoding of the object id.
https://apidock.com/ruby/Object/to_s
上例中对象id的编码为0x00007fac5eb6afc8
.
在 How does object_id assignment work? 他们解释
In MRI the object_id of an object is the same as the VALUE that represents the object on the C level.
所以我对比了object_id
和object id的编码不一样
[2] pry(main)> shape = Shape.new(4,4)
=> #<Shape:0x00007fac5eb6afc8 @num_sides=4, @side_length=4>
[3] pry(main)> shape.object_id
=> 70189150066660
对象id的编码到底是什么?它似乎不是 object_id
.
将 object_id
或 __id__
视为对象的 "pointer"。它在技术上不是指针,但确实包含可用于检索内部 C VALUE
.
的唯一值
对于某些数据类型,它的值有一定的模式,正如您可以通过 to_s
的十六进制表示形式看到的那样。我不会详细介绍所有细节,因为已经有很多关于 SO 解释的答案,并且已经从评论中链接,但是整数(最多 FIXNUM_MAX
,具有可预测的值和特殊常量,如 true
、false
和 nil
在每个 运行 中总是有相同的 object_id
。
简单地说,它只不过是一个数字,显示为十六进制(以 16 为底)值,而不是任何实际的 "encoding" 或密码。
根据您对问题的最新编辑,将对此进行更多扩展。正如您发布的那样,您在 to_s
中看到的十六进制数是对象的内部 C VALUE
的值。 VALUE
是一种 C 数据类型(无符号,指针大小数字),每个 Ruby 对象都用 C 代码表示。正如@Stefan 在评论中指出的那样,对于非整数类型(我只针对 MRI 版本),它是 object_id
值的两倍。不是你可能关心,但你可以移动一个整数的位来预测那些的值。
因此,以你为例。
0x00007fac5eb6afc8
的值是数字的简单十六进制表示法。它使用以 16 为基数的计数系统,而不是我们在日常生活中更习惯的以 10 为基数的十进制系统。这只是看待同一个数字的不同方式。
所以,使用那个逻辑。
a = 0x00007fac5eb6afc8
#=> 140378300133320 # Decimal representation
a /= 2 # Remember, non-integers are half of this value
#=> 70189150066660 # Your object_id
你能得到的最佳答案是:你不知道,你不应该知道。
Ruby 准确保证关于对象 ID 的三件事:
- 对象在其生命周期内具有相同的 ID。
- 没有两个对象同时具有相同的 ID。
- ID 是整数。
特别是,这意味着您不能依赖具有特定 ID 的特定对象(例如,nil
具有 ID 8
)。这也意味着可以重复使用 ID。您应该将其视为不透明的标识符。
并且,正如您引用的那样,默认 Object#to_s
使用 ID 的 "some" 编码。
这就是你所知道的,也是你应该依赖的。特别是,您应该 永远不要 尝试解析 ID 或 Object#to_s
.
所以,Object#to_s
的ID部分是ID的"some unspecified encoding",它本身就是"some opaque identifier"。
其他所有内容都故意未指定,以便不同的实现可以根据其特定需求做出不同的选择。例如,将对象 ID 绑定到内存地址是愚蠢的,因为像 JRuby、Opal、IronPython、MagLev 和 Topaz 运行 这样的实现在 "memory address" 的概念不存在的平台上甚至存在! Rubinius 使用移动垃圾收集器,对象可以在内存中移动,因此它们的地址会发生变化。
在 Ruby 中,对象的 to_s
包括对象 ID 的编码。
[2] pry(main)> shape = Shape.new(4,4)
=> #<Shape:0x00007fac5eb6afc8 @num_sides=4, @side_length=4>
文档中说
Returns a string representing obj. The default to_s prints the object’s class and an encoding of the object id. https://apidock.com/ruby/Object/to_s
上例中对象id的编码为0x00007fac5eb6afc8
.
在 How does object_id assignment work? 他们解释
In MRI the object_id of an object is the same as the VALUE that represents the object on the C level.
所以我对比了object_id
和object id的编码不一样
[2] pry(main)> shape = Shape.new(4,4)
=> #<Shape:0x00007fac5eb6afc8 @num_sides=4, @side_length=4>
[3] pry(main)> shape.object_id
=> 70189150066660
对象id的编码到底是什么?它似乎不是 object_id
.
将 object_id
或 __id__
视为对象的 "pointer"。它在技术上不是指针,但确实包含可用于检索内部 C VALUE
.
对于某些数据类型,它的值有一定的模式,正如您可以通过 to_s
的十六进制表示形式看到的那样。我不会详细介绍所有细节,因为已经有很多关于 SO 解释的答案,并且已经从评论中链接,但是整数(最多 FIXNUM_MAX
,具有可预测的值和特殊常量,如 true
、false
和 nil
在每个 运行 中总是有相同的 object_id
。
简单地说,它只不过是一个数字,显示为十六进制(以 16 为底)值,而不是任何实际的 "encoding" 或密码。
根据您对问题的最新编辑,将对此进行更多扩展。正如您发布的那样,您在 to_s
中看到的十六进制数是对象的内部 C VALUE
的值。 VALUE
是一种 C 数据类型(无符号,指针大小数字),每个 Ruby 对象都用 C 代码表示。正如@Stefan 在评论中指出的那样,对于非整数类型(我只针对 MRI 版本),它是 object_id
值的两倍。不是你可能关心,但你可以移动一个整数的位来预测那些的值。
因此,以你为例。
0x00007fac5eb6afc8
的值是数字的简单十六进制表示法。它使用以 16 为基数的计数系统,而不是我们在日常生活中更习惯的以 10 为基数的十进制系统。这只是看待同一个数字的不同方式。
所以,使用那个逻辑。
a = 0x00007fac5eb6afc8
#=> 140378300133320 # Decimal representation
a /= 2 # Remember, non-integers are half of this value
#=> 70189150066660 # Your object_id
你能得到的最佳答案是:你不知道,你不应该知道。
Ruby 准确保证关于对象 ID 的三件事:
- 对象在其生命周期内具有相同的 ID。
- 没有两个对象同时具有相同的 ID。
- ID 是整数。
特别是,这意味着您不能依赖具有特定 ID 的特定对象(例如,nil
具有 ID 8
)。这也意味着可以重复使用 ID。您应该将其视为不透明的标识符。
并且,正如您引用的那样,默认 Object#to_s
使用 ID 的 "some" 编码。
这就是你所知道的,也是你应该依赖的。特别是,您应该 永远不要 尝试解析 ID 或 Object#to_s
.
所以,Object#to_s
的ID部分是ID的"some unspecified encoding",它本身就是"some opaque identifier"。
其他所有内容都故意未指定,以便不同的实现可以根据其特定需求做出不同的选择。例如,将对象 ID 绑定到内存地址是愚蠢的,因为像 JRuby、Opal、IronPython、MagLev 和 Topaz 运行 这样的实现在 "memory address" 的概念不存在的平台上甚至存在! Rubinius 使用移动垃圾收集器,对象可以在内存中移动,因此它们的地址会发生变化。