Объяснение шестнадцатеричного идентификатора объекта Ruby
Вы когда-нибудь задумывались, откуда взялось шестнадцатеричное значение и что оно означает?
В какой-то момент своей жизни вы, вероятно, спросили себя: что это за странное шестнадцатеричное значение рядом с именем класса, когда вы создаете объект или запускаете метод проверки?
Короткий ответ: это измененный идентификатор объекта. Могу себе представить, что этот ответ вас не удовлетворит. Меня это тоже не удовлетворяет. Итак, вот длинный ответ:
В Ruby Interpreter (MRI) Matz’а object_id совпадает со VALUE объекта в C (в котором записан MRI). Это ЗНАЧЕНИЕ является указателем на место в памяти, где хранится объект (данные). Это справедливо для любого объекта, за некоторыми исключениями. Это основная причина, по которой экземпляры одного и того же приложения будут возвращать разные идентификаторы для одного и того же объекта.
Теперь я использовал слово «совпадает», потому что ЗНАЧЕНИЕ и object_id тесно связаны, даже в некоторых случаях они абсолютно одинаковы.
Важно знать, что VALUE имеет отдельные пространства имен для разных типов данных.
VALUE space false 00000000000000000000000000000000 true 00000000000000000000000000000010 nil 00000000000000000000000000000100 symbol ssssssssssssssssssssssss00001110 object oooooooooooooooooooooooooooooo00 fixnum fffffffffffffffffffffffffffffff1
То же самое и с object_id.
object_id space false 00000000000000000000000000000000 true 00000000000000000000000000000010 nil 00000000000000000000000000000100 symbol 0000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 object ooooooooooooooooooooooooooooooo0 fixnum fffffffffffffffffffffffffffffff1
Из приведенных выше примеров вы можете понять, что nil, true, false и fixnums одинаковы для обоих. С другой стороны, объекты сдвигаются на один бит влево от соответствующего ЗНАЧЕНИЯ.
Поэтому, когда вы запускаете метод object_id, вы можете увидеть представление из пространства object_id. Когда вы запускаете метод проверки, вы можете увидеть представление из пространства ЗНАЧЕНИЕ, преобразованное в шестнадцатеричное число.
obj = Object.new #=> #<Object:0x00007fb7981e4068> obj.object_id #=> 70213253931060 obj.object_id << 1 #=> 140426507862120 _.to_s(16) #=> "7fb7981e4068"
И это может быть все. Но один вопрос остается без ответа: почему nil, true, false и fixnums не ведут себя так?
Ответ: по соображениям производительности. Поскольку эти объекты интенсивно используются повторно, ЗНАЧЕНИЕ не содержит указатель на место в памяти, но содержит сам объект (данные).
Из приведенных ниже списков кода видно, что идентификаторы объектов для false, true, nil и fixnums (n) равны 0, 2, 4 и 2n+1 соответственно. Они никогда не являются действительными адресами, поэтому их нельзя путать с указателями.
false.object_id #=> 0 true.object_id #=> 2 nil.object_id #=> 4 1.object_id #=> 3 2.object_id #=> 5 10.object_id #=> 21