2010-10-24 2 views
4

Краткая версия: Метод по умолчанию inspect метод для класса отображает адрес объекта. * Как это сделать в собственном inspect методе?Адрес объекта в Ruby

* (Чтобы было ясно, я хочу 8-значный шестнадцатеричный номер, который вы обычно получаете от inspect. Я не забочусь о фактическом адресе памяти. Я просто назвав его адрес в памяти, потому что она выглядит . как один я знаю, что Руби является память безопасной)

Длинная версия:. у меня есть два класса, Thing и ThingList. ThingList является подклассом Array, специально разработанным для хранения вещей. Из-за природы Вещей и способа их использования в моей программе Вещи имеют переменную экземпляра @container, которая указывает на ThingList, который содержит Thing.

Возможно, что две вещи имеют точно такие же данные. Поэтому, когда я отлаживаю приложение, единственный способ, которым я могу надежно различать две вещи, - использовать inspect, который отображает их адрес. Однако, когда я inspect a Thing, я получаю страницы на страницах вывода, потому что inspect будет рекурсивно проверять @container, в результате чего каждую вещь в списке также проверят!

Все, что мне нужно, это первая часть этого вывода. Как я могу написать собственный метод inspect на Thing, который просто отобразит это?

#<Thing:0xb7727704> 

EDIT: Я просто понял, что по умолчанию to_s делает именно это. Раньше я этого не замечал, потому что у меня есть пользовательский to_s, который предоставляет удобные для пользователя сведения об объекте.

Предположим, что я не могу использовать to_s, и что я должен написать обычай inspect.

ответ

10

Вы можете получить адрес с помощью object_id и умножив его на 2 * и отобразить его в шестнадцатеричном с помощью sprintf (ака %):

"#<Thing:0x%08x>" % (object_id * 2) 

Конечно, до тех пор, как вам нужно только номер, быть уникальным и не волнует, что это фактический адрес, вы можете просто оставить * 2.

* По причинам, которые вам не нужны, чтобы понять (что означает: я не понимаю их), object_id возвращает половину адреса памяти объекта, так что вам нужно умножить на 2, чтобы получить фактический адрес.

+1

Строго говоря, я не думаю, что [object_id] (http://ruby-doc.org/core/classes/Object.html#M000339) возвращает адрес объекта, но уникальный идентификатор должен решить проблему OP , – maerics

+0

@maerics: В MRI это определенно делает (для всех объектов кроме целых, символов, true, false и nil). – sepp2k

+0

Хм, возможно, на некоторых версиях; мой ближайший MRI (1.8.7 darwin) определенно показывает разные значения между стандартными 'inspect' и' object_id'. – maerics

0

Вместо подкласса Array экземпляры вашего класса могут делегировать один из требуемых методов, чтобы вы не наследовали переопределенный метод inspect.

1

Это невозможно. В Ruby нет способа получить адрес памяти объекта, так как Ruby - это безопасный для памяти язык, который (по дизайну) не имеет методов прямого доступа к памяти. На самом деле, во многих реализациях Ruby объекты не имеют , имеют адрес памяти.И в большинстве реализаций, которые do отображает объекты непосредственно в память, адрес памяти потенциально изменяется после каждой сборки мусора.

Причина, по которой использование адреса памяти в качестве идентификатора в текущих версиях MRI и YARV происходит случайно, заключается в том, что у них есть реализация crappy сборщика мусора, которая никогда не дефрагментирует память. Во всех других реализациях есть сборщики мусора, которые делают дефрагментации памяти и, таким образом, перемещают объекты в памяти, тем самым изменяя их адрес.

Если вы связываете свою реализацию с адресом памяти, ваш код будет работать только на медленных реализациях с помощью дрянных сборщиков мусора. И даже не гарантировано, что у MRI и YARV всегда будут дрянные сборщики мусора, по сути, в обеих реализациях сборщик мусора был идентифицирован как один из основных узких мест в производительности, и можно с уверенностью предположить, что будет быть изменениями в сборщиках мусора. Уже есть некоторые существенные изменения в сборщике мусора YARV в SVN, который будет частью YARV 1.9.3 и YARV 2.0.

Если вы хотите ID для объектов, используйте Object#object_id.

+0

Должен ли MRI/YARV использовать идентификатор объекта, а не адрес памяти для проверки? –

Смежные вопросы