在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
。
答案 0 :(得分:2)
将object_id
或__id__
视为对象的“指针”。从技术上讲,它不是指针,但确实包含可用于检索内部C VALUE
的唯一值。
某些数据类型具有其值的模式,如使用to_s
进行十六进制表示所见。我不会涉及所有细节,因为关于SO的解释已经有很多答案,并且已经通过注释链接了,但是整数(最大为FIXNUM_MAX
,具有可预测的值,以及诸如{{1} },true
和false
在每次运行中始终具有相同的nil
。
简单地说,它不过是一个数字,并显示为十六进制(以16为底)值,而不是任何实际的“编码”或密码。
根据您对问题的最新编辑内容,可以对此进行更多扩展。如您所发布的,您在object_id
中看到的十六进制数字是对象内部C to_s
的值。 VALUE
是一种C数据类型(无符号,指针大小数字),每个Ruby对象都用C代码表示。正如@Stefan在评论中指出的那样,对于非整数类型(我只说MRI版本),它是VALUE
值的两倍。并不是您可能在乎,但是您可以移动整数的位以预测这些值。
因此,以您为例。
object_id
的值是数字的简单十六进制表示法。它使用以16为基数的计数系统,而不是我们在日常生活中习惯的以10为基数的十进制系统。这只是看相同数字的另一种方式。
因此,使用该逻辑。
0x00007fac5eb6afc8
答案 1 :(得分:0)
您可以获得的最佳答案是:您不知道,也不需要。
Ruby保证有关对象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使用移动的垃圾收集器,对象可以在内存中四处移动,从而改变其地址。