8

クラスのオブジェクトがあり、それを で複製したいと考えていdupます。インスタンス変数の 1 つが配列で、それを参照しているようです。dup は実際に DUPLICATE を作成したと思いました。

これが私の IRB セッションです。

irb(main):094:0> class G
irb(main):095:1> attr_accessor :iv
irb(main):096:1> def initialize
irb(main):097:2> @iv = [1,2,3]
irb(main):098:2> end
irb(main):099:1> end
=> nil

irb(main):100:0> a=G.new
=> #<G:0x27331f8 @iv=[1, 2, 3]>

irb(main):101:0> b=a.dup
=> #<G:0x20e4730 @iv=[1, 2, 3]>

irb(main):103:0> b.iv<<4
=> [1, 2, 3, 4]
irb(main):104:0> a
=> #<G:0x27331f8 @iv=[1, 2, 3, 4]

参照ではなく、まったく新しい変数を作成するaため、変更されないことが期待されます。dup

[1,2,3]また、 でスカラーに置き換えた場合G::initialize、はそれを参照しないことに注意してくださいdup

4

3 に答える 3

7

のデフォルトの実装でdupclone浅いコピーを作成するだけなので、2 つのオブジェクトが同じ配列を参照することになります。必要な動作を得るには、関数を定義する必要があります (これはandinitialize_copyによって呼び出されます)。dupclone

class G
  attr_accessor :iv
  def initialize_copy(source)
    super
    @iv = source.iv.dup
  end
end

次に、2 つのオブジェクトは 2 つの異なる配列を参照します。dup配列に変更可能なオブジェクトが含まれている場合は、配列内の各オブジェクトをさらに深くしたい場合があります。

def initialize_copy(source)
  super
  @iv = source.iv.collect &:dup
end
于 2012-01-01T02:14:56.783 に答える
6

dup浅いコピーを作成します。インスタンス変数によって参照されるオブジェクトはコピーされません。

標準的な (たとえば、Really Easy) ディープ コピー ハックは、マーシャリング/アンマーシャリングです。これは、実際のユースケースで機能する場合と機能しない場合があります (これは単純化された例であると仮定します)。そうでない場合、またはマーシャリングが非効率的である場合は、initialize_copyルートの方が適しています。

pry(main)> a = G.new
=> #<G:0x9285628 @iv=[1, 2, 3]>
pry(main)> b = a.dup
=> #<G:0x92510a8 @iv=[1, 2, 3]>
pry(main)> a.iv.__id__
=> 76819210
pry(main)> b.iv.__id__
=> 76819210
pry(main)> b = Marshal::load(Marshal.dump(a))
=> #<G:0x9153c3c @iv=[1, 2, 3]>
pry(main)> a.__id__
=> 76819220
pry(main)> b.__id__
=> 76193310
于 2012-01-01T02:09:01.930 に答える
0

オーバーライドdupまたはcloneメソッド:

  def dup
    Marshal::load(Marshal.dump(self))
  end
于 2016-05-03T19:17:14.320 に答える