5

短いバージョン:クラス のデフォルトのメソッドは、オブジェクトのアドレスを表示します。*独自のカスタムメソッドでinspectこれを行うにはどうすればよいですか?inspect

*(明確にするために、通常から取得する8桁の16進数が必要ですinspect。実際のメモリアドレスは気にしません。メモリアドレスのように見えるので、単にメモリアドレスと呼んでいます。Rubyはメモリセーフ。)

ロングバージョン: 2つのクラスがThingありThingListます。 は、 Thingsを保持するために特別に設計されThingListたのサブクラスです。ArrayThingsの性質とプログラムでの使用方法により、Thingsには、を保持する@containerを指すインスタンス変数があります。ThingListThing

2つのThingがまったく同じデータを持つ可能性があります。したがって、アプリケーションをデバッグするとき、2つのThingを確実に区別できる唯一の方法はinspect、アドレスを表示するを使用することです。ただし、私がinspectaを実行するThingと、出力のページごとにページが取得されます。これinspectは、再帰的に検査するため@container、リスト内のすべてのThingも検査されるためです。

必要なのは、その出力の最初の部分だけです。inspectこれを表示するだけのカスタムメソッドを作成するにはどうすればよいThingですか?

#<Thing:0xb7727704>

編集:to_s私はデフォルトがまさにこれ を行うことに気づきました。to_sオブジェクトに関する人間が読める形式の詳細を提供するカスタムがあるため、これは以前は気づいていませんでした。

to_sを使用できず、カスタムを作成する必要があると想定しますinspect

4

3 に答える 3

11

object_idを使用してアドレスを取得し、それを2 *sprintfで乗算し、 (aka %) を使用して16進数で表示できます。

"#<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 1.9.3 および YARV 2.0 の一部となる SVN の YARV のガベージ コレクターには、すでにいくつかの主要な変更があります。

オブジェクトの ID が必要な場合は、 を使用しますObject#object_id

于 2010-10-25T01:22:11.963 に答える
0

Array をサブクラス化する代わりに、オーバーライドされたメソッドを継承しないように、クラス インスタンスを必要なメソッドの 1 つに委譲することができますinspect

于 2010-10-24T21:43:32.413 に答える