Ruby对象to_s对象ID的编码是什么?

时间:2018-08-17 14:41:42

标签: ruby object document tostring

在Ruby中,对象上的to_s包含对象ID的编码。

[2] pry(main)> shape = Shape.new(4,4)
=> #<Shape:0x00007fac5eb6afc8 @num_sides=4, @side_length=4>

在文档中说

  

返回代表obj的字符串。默认的to_s打印对象的类和对象id的编码。   https://apidock.com/ruby/Object/to_s

在上面的示例中,对象ID的编码为0x00007fac5eb6afc8

How does object_id assignment work?中,他们解释

  

在MRI中,对象的object_id与代表C级对象的VALUE相同。

因此,我将其与object_id进行了比较,它与对象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

2 个答案:

答案 0 :(得分:2)

object_id__id__视为对象的“指针”。从技术上讲,它不是指针,但确实包含可用于检索内部C VALUE的唯一值。

某些数据类型具有其值的模式,如使用to_s进行十六进制表示所见。我不会涉及所有细节,因为关于SO的解释已经有很多答案,并且已经通过注释链接了,但是整数(最大为FIXNUM_MAX,具有可预测的值,以及诸如{{1} },truefalse在每次运行中始终具有相同的nil

简单地说,它不过是一个数字,并显示为十六进制(以16为底)值,而不是任何实际的“编码”或密码。

根据您对问题的最新编辑内容,可以对此进行更多扩展。如您所发布的,您在object_id中看到的十六进制数字是对象内部C to_s的值。 VALUE是一种C数据类型(无符号,指针大小数字),每个Ruby对象都用C代码表示。正如@Stefan在评论中指出的那样,对于非整数类型(我只说MRI版本),它是VALUE值的两倍。并不是您可能在乎,但是您可以移动整数的位以预测这些值。

因此,以您为例。

object_id的值是数字的简单十六进制表示法。它使用以16为基数的计数系统,而不是我们在日常生活中习惯的以10为基数的十进制系统。这只是看相同数字的另一种方式。

因此,使用该逻辑。

0x00007fac5eb6afc8

答案 1 :(得分:0)

您可以获得的最佳答案是:您不知道,也不需要。

Ruby保证有关对象ID的三件事:

  1. 对象在其生存期内具有相同的ID。
  2. 没有两个对象具有相同的ID。
  3. ID是整数。

特别是,这意味着您不能依赖具有特定ID的特定对象(例如,具有ID nil的{​​{1}})。这也意味着可以重复使用ID。您应该将其视为不透明的标识符。

而且,正如您所引用的,默认的8使用ID的“某种”编码。

这就是您所知道的,以及您应该依靠的一切。特别是,您应该从不尝试解析ID或Object#to_s

因此,Object#to_s的ID部分是ID的“某些未指定编码”,而ID本身就是“一些不透明的标识符”。

故意忽略所有其他内容,以便不同的实现可以做出满足其特定需求的不同选择。例如,将对象ID绑定到内存地址是愚蠢的,因为JRuby,Opal,IronPython,MagLev和Topaz之类的实现在甚至不存在“内存地址”概念的平台上运行! Rubinius使用移动的垃圾收集器,对象可以在内存中四处移动,从而改变其地址。