2010-11-17 24 views
5

J'ai un struct dans mon code Ruby qui ressemble un peu à cePourquoi String :: sub!() Modifie l'original d'un objet cloné dans Ruby?

Parameter = Struct.new(:name, :id, :default_value, :minimum, :maximum) 

plus tard, je créer une instance de cette structure en utilisant

freq = Parameter.new('frequency', 15, 1000.0, 20.0, 20000.0) 

À un moment donné, il me faut une copie exacte de ce struct, donc j'appelle

newFreq = freq.clone 

Ensuite, je change le nom de newFreq

newFreq.name.sub!('f', 'newF') 

Qui, miraculeusement, change aussi freq.name! Une affectation simple comme newFreq.name = 'newFrequency' ne change pas freq.

Est-ce la façon dont cela est censé fonctionner?

Modifier: Est-ce une bonne idée d'utiliser une classe au lieu d'une structure et de surcharger clone pour faire une copie profonde?

Répondre

10

newFreq est une copie superficielle de freq. Cela signifie que chacune des références stockées à l'intérieur de newFreq pointe vers l'objet comme celles stockées dans freq. Vous pouvez changer l'endroit où les références pointent indépendamment (newFreq.name = newFreq.name.sub 'f','newF'), mais si vous appelez une méthode qui mute l'objet, newFreq et freq seront affectées.

Voir aussi http://en.wikipedia.org/wiki/Object_copy

8

La méthode Object#clone effectue une copie peu profonde. Vous avez besoin de copie profonde pour faire le travail.

Suivez this link pour en savoir plus sur la copie profonde dans Ruby.