2

Fixnumin docの次の機能を見つけました。

Fixnumオブジェクトには即時の価値があります。これは、それらがパラメーターとして割り当てられたり渡されたりすると、そのオブジェクトへの参照ではなく、実際のオブジェクトが渡されることを意味します。

同じことを IRB で表示できますか? それなら、私が正しく理解してくれることを願っていますか?

代入は、Fixnum オブジェクトの別名ではありません。

それは実際には何をしますか?

与えられた整数値に対して事実上 1 つの Fixnum オブジェクト インスタンスしか存在しないため、たとえば、シングルトン メソッドを に追加することはできません Fixnum

オブジェクト インスタンスsingletonを含むメソッドを追加しない理由が理解できませんでした。Fixnum

以下のように、2番目のポイントを試してみました。

a = 1                      # => 1
a.class                    # => Fixnum
b = a                      # => 1
b.class                    # => Fixnum
a == b                     # => true
a.equal? b                 # => true
a.object_id == b.object_id # => true

しかし、まだ私は混乱しています。これらの機能の核心を理解するために、ここで私を助けてくれる人はいますか?

4

2 に答える 2

11

Rubyでは、ほとんどのオブジェクトは、クラス変数とインスタンス変数を格納するためにメモリを必要とします。このメモリが割り当てられると、Rubyはこのメモリ位置によって各オブジェクトを表します。オブジェクトが変数に割り当てられたり、関数に渡されたりする場合、渡されるのはこのメモリの場所であり、このメモリのデータではありません。シングルトンメソッドはこれを利用します。シングルトンメソッドを定義すると、Rubyはオブジェクトクラスを新しいシングルトンクラスにサイレントに置き換えます。各オブジェクトはそのクラスを格納するため、Rubyはオブジェクトのクラスを、シングルトンメソッドを実装する(そして元のクラスから継承する)新しいクラスに簡単に置き換えることができます。

これは、即時値であるオブジェクトtrue(、、、、すべてのシンボル、およびFixnum内に収まるほど小さい整数)には当てはまりません。Rubyは、これらのオブジェクトのインスタンスにメモリを割り当てません。オブジェクトをメモリ内の場所として内部的に表しません。代わりに、内部表現に基づいてオブジェクトのインスタンスを推測します。これが意味することは2つあります。falsenil

  1. 各オブジェクトのクラスは、メモリの特定の場所に保存されなくなり、代わりに、直接のオブジェクトのタイプによって暗黙的に決定されます。これが、Fixnumsがシングルトンメソッドを持つことができない理由です。

  2. 同じ状態のイミディエイトオブジェクト(たとえば、整数2378の2つのFixnum)は、実際には同じインスタンスです。これは、インスタンスがこの状態によって決定されるためです。

これをよりよく理解するために、Fixnumでの次の操作を検討してください。

>> x = 3 + 7
=> 10
>> x.object_id == 10.object_id
=> true
>> x.object_id == (15-5).object_id
=> true

ここで、文字列を使用してそれらを検討します。

>> x = "a" + "b"
=> "ab"
>> x.object_id == "ab".object_id
=> false
>> x.object_id == "Xab"[1...3].object_id
=> false
>> x == "ab"
=> true
>> x == "Xab"[1...3]
=> true

FixnumのオブジェクトIDが等しい理由は、それらが同じ内部表現を持つ即時オブジェクトであるためです。一方、文字列は割り当てられたメモリに存在します。各文字列のオブジェクトIDは、メモリ内のオブジェクト状態の場所です。

いくつかの低レベルの情報

これを理解するには、Ruby(少なくとも1.8および1.9)がFixnumを内部でどのように処理するかを理解する必要があります。Rubyでは、すべてのオブジェクトはCコードで型の変数によって表されますVALUE。Rubyは、次の要件を課していますVALUE

  1. タイプVALUEは、ポインターを保持するのに十分なサイズの最小の整数です。これは、Cではそれを意味しsizeof(VALUE) == sizeof(void*)ます。

  2. 非即時オブジェクトは、4バイト境界に揃える必要があります。これは、Rubyによって割り当てられたすべてのオブジェクトが4*i整数のアドレスを持つことを意味しますi。これは、すべてのポインタの最下位2ビットの値がゼロであることも意味します。

最初の要件により、Rubyはオブジェクトへのポインターと即値の両方を型の変数に格納できますVALUE。2番目の要件により、Rubyは2つの最下位ビットに基づいてFixnumオブジェクトとSymbolオブジェクトを検出できます。

これをより具体的にするために、32ビットアーキテクチャでz呼び出すRubyオブジェクトの内部バイナリ表現について考えてみます。Rz

MSB                                   LSB
  3           2            1            
 1098 7654 3210 9876 5432 1098 7654 32 10
 XXXX XXXX XXXX XXXX XXXX XXXX XXXX AB CD

次に、RubyはRz、の表現をz次のように解釈します。

  1. の場合D==1zはFixnumです。このFixnumの整数値は、表現の上位31ビットに格納され、算術右シフトを実行してこれらのビットに格納されている符号付き整数を復元することによって復元されます。

  2. 3つの特別な表現がテストされます(すべてD==0

    • の場合Rz==0zfalse
    • の場合Rz==2ztrue
    • の場合Rz==4znil
  3. の場合ABCD == 1110、「z」はシンボルです。シンボルは、最下位8ビットを右シフトすることによって(つまり、z>>8Cで)一意のIDに変換されます。32ビットアーキテクチャでは、これにより2 ^ 24の異なるID(1,000万を超える)が可能になります。64ビットアーキテクチャでは、これにより2^48の異なるIDが許可されます。

  4. それ以外Rzの場合は、Rubyオブジェクトのインスタンスのメモリ内のアドレスを表し、のタイプはzその場所のクラス情報によって決定されます。

于 2013-03-07T01:15:30.047 に答える
1

良い...

  1. これは、MRI に関する内部実装の詳細です。ご覧のとおり、Ruby (C 側) では、すべての Ruby オブジェクトはVALUE. ほとんどの場合、aVALUEはスタック上に存在するオブジェクトへのポインターです。ただし、即時値 (Fixnums、true、false、nil、およびその他) はVALUE、オブジェクトへのポインターが通常存在する場所に存在します。
  2. 変数をまったく同じオブジェクトにします。これが内部でどのように機能するかはわかりませんが、VALUEそれ自体に割り当てられますが、そうです。
  3. プログラムで数値を使用するたびに1、同じオブジェクトを使用しているためです。したがって、 でシングルトン メソッドを定義すると、プログラム1すべての場所、必要なプログラムなどにそのシングルトン メソッドが含まれます。また、シングルトン メソッドは通常、ローカル モンキーパッチに使用されます。したがって、これを防ぐために、Ruby は許可していません。
于 2013-03-06T14:52:20.863 に答える