J'ai un objet d'une classe et je veux dupliquer avec Voici ma session IRB: P> DUP code>. L'une des variables d'instance est un tableau, et il semble y référencer. Je pensais que DUP a créé un duplicata.
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]
3 Réponses :
DUP code> Craques une copie peu profonde
; Les objets visés par des variables d'instance ne sont pas copiés.
Le piratage de la copie en profondeur (par exemple, vraiment facile), qui peut ou non fonctionner dans votre usecase réelle (en supposant qu'il s'agisse d'un exemple simplifié). Si ce n'est pas le cas, ou si marshalling est à inefficace, le itinéraire Initialize_Copy code> est une meilleure option. P>
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
La mise en oeuvre par défaut de Les deux objets se réfèrent à deux tableaux différents. Si les tableaux ont des objets mutables en eux, vous voudrez peut-être aller même plus profond et DUP code> et
clone code> Il suffit de créer une copie peu profonde, vous aurez donc deux objets faisant référence au même tableau. Pour obtenir le comportement que vous voulez, vous devez définir une fonction
initialize_copy code> (qui est appelée par
DUP code> et
clone code>):
DUP code> chaque objet dans les tableaux: p>
def initialize_copy(source)
super
@iv = source.iv.collect &:dup
end
remplacement DUP code> ou
clone code> Méthode: