226 votes

Quelle est la différence entre les méthodes dup et clone de Ruby?

Le Ruby docs pour dup - dire:

En général, clone et dup peut avoir différentes sémantiques en descendant les classes. Alors qu' clone est utilisé pour dupliquer un objet, y compris son état interne, dup utilise généralement la classe de l'héritière de l'objet pour créer la nouvelle instance.

Mais quand je fais quelques test, j'ai constaté qu'ils sont en fait les mêmes:

class Test
   attr_accessor :x
end

x = Test.new
x.x = 7
y = x.dup
z = x.clone
y.x => 7
z.x => 7

Quelles sont donc les différences entre les deux méthodes?

309voto

Jeremy Roman Points 9211

Les sous-classes peuvent remplacer ces méthodes pour fournir des sémantiques différentes. En Object lui-même, il y a deux différences essentielles.

Tout d'abord, clone des copies de la classe singleton, alors que dup ne le sont pas.

o = Object.new
def o.foo
  42
end

o.dup.foo   # raises NoMethodError
o.clone.foo # returns 42

Deuxièmement, clone préserve l'état congelé, alors que dup ne le sont pas.

class Foo
  attr_accessor :bar
end
o = Foo.new
o.freeze

o.dup.bar = 10   # succeeds
o.clone.bar = 10 # raises RuntimeError

Le Rubinius mise en œuvre de ces méthodes est souvent ma source pour répondre à ces questions, car il est tout à fait clair, et assez conforme Ruby mise en œuvre.

195voto

jvalanen Points 41

En ce qui concerne les ActiveRecords, il existe également une différence significative:

dup crée un nouvel objet sans qu'il soit défini, vous pouvez donc enregistrer un nouvel objet dans la base de données en appuyant sur .save

 2.1.2 :021 > category2 = category.dup
 => #<Category id: nil, name: "Favorites"> 
 

clone crée un nouvel objet avec le même identifiant, de sorte que toutes les modifications apportées à ce nouvel objet écraseront l’enregistrement original si vous frappez.

 2.1.2 :018 > category2 = category.clone
 => #<Category id: 1, name: "Favorites">
 

30voto

Jonathan Fretheim Points 592

Une différence est avec les objets gelés. Le clone d'un objet gelé est également gelé (alors qu'un dup d'un objet gelé ne l'est pas).

 class Test
  attr_accessor :x
end
x = Test.new
x.x = 7
x.freeze
y = x.dup
z = x.clone
y.x = 5 => 5
z.x = 5 => TypeError: can't modify frozen object
 

Une autre différence est avec les méthodes singleton. Même histoire ici, dup ne les copie pas, mais clone fait.

 def x.cool_method
  puts "Goodbye Space!"
end
y = x.dup
z = x.clone
y.cool_method => NoMethodError: undefined method `cool_method'
z.cool_method => Goodbye Space!
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X