5

简短版本:类 的默认inspect方法显示对象的地址。* 如何在inspect我自己的自定义方法中执行此操作?

*(要清楚,我想要你通常会得到的 8 位十六进制数inspect。我不关心实际的内存地址。我只是称它为内存地址,因为它看起来像一个。我知道 Ruby内存安全。)

长版: 我有两个课程,Thing并且ThingList. ThingListArray专门设计用于保存事物的子类。由于 Things 的性质以及它们在我的程序中的使用方式,Things 有一个实例变量@container,它指向ThingList保存Thing.

两个事物可能具有完全相同的数据。因此,当我调试应用程序时,我能够可靠地区分两个事物的唯一方法是使用inspect,它会显示它们的地址。但是,当我inspectaThing时,我会得到一页又一页的输出,因为inspect将递归检查@container,导致列表中的每个事物也被检查!

我需要的只是该输出的第一部分。我怎样才能编写一个自定义inspect方法Thing来显示这个?

#<Thing:0xb7727704>

编辑: 我刚刚意识到默认值就是to_s这样做的。我之前没有注意到这一点,因为我有一个自定义to_s,可以提供有关对象的可读详细信息。

假设我不能使用to_s,我必须编写一个自定义inspect

4

3 回答 3

11

您可以使用 object_id 获取地址并将其乘以 2 * 并使用sprintf(aka %) 以十六进制显示:

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

当然,只要你只需要数字是唯一的并且不在乎它是实际地址,你可以省略* 2.

*出于你不需要理解的原因(意思是:我不理解它们),object_id返回一半对象的内存地址,所以你需要乘以 2 才能得到实际地址。

于 2010-10-24T21:34:41.580 回答
2

这是不可能的。Ruby 无法获取对象的内存地址,因为 Ruby 是一种内存安全的语言,它(根据设计)没有直接访问内存的方法。事实上,在 Ruby 的许多实现中,对象甚至没有内存地址。在大多数将对象直接映射到内存的实现中内存地址可能会在每次垃圾回收后发生变化。

在当前版本的 MRI 和 YARV 中使用内存地址作为标识符意外工作的原因是因为它们有一个糟糕的垃圾收集器实现,从不对内存进行碎片整理。所有其他实现都有垃圾收集器,它们对内存进行碎片整理,从而在内存中移动对象,从而改变它们的地址。

如果你将你的实现与内存地址联系起来,你的代码将只能在具有蹩脚的垃圾收集器的慢速实现上工作。甚至不能保证 MRI 和 YARV 总是有蹩脚的垃圾收集器,事实上,在这两种实现中,垃圾收集器已被确定为主要的性能瓶颈之一可以肯定地假设将会对垃圾收集器。YARV 的垃圾收集器在 SVN 中已经有了一些重大变化,这将成为 YARV 1.9.3 和 YARV 2.0 的一部分。

如果您想要对象的 ID,请使用Object#object_id.

于 2010-10-25T01:22:11.963 回答
0

而不是继承 Array 您的类实例可以委托给一个所需的方法,这样您就不会继承被覆盖的inspect方法。

于 2010-10-24T21:43:32.413 回答