Ruby définit 1) est une liste complète des classes (au moins des classes de base), qui n'autorisent pas 2) Quel est le problème avec #clone code> dans objet fort>.
À ma surprise, certaines classes soulèvent des exceptions lors de l'appelant.
J'ai trouvé
#clone code>?
Ou existe-t-il un moyen de détecter si une classe spécifique prend en charge
#clone code>? P>
42.Clone code>? p>
6 Réponses :
Vous ne pouvez pas cloner des classes immuables. C'est à dire. Vous ne pouvez avoir qu'une seule instance d'objet 42 (en tant que fixnum), mais peut avoir de nombreuses instances de "42" (car la chaîne est mutable). Vous ne pouvez pas cloner des symboles aussi bien qu'ils sont quelque chose comme des chaînes immuables. P>
Vous pouvez vérifier cela dans IRB avec méthode Object_ID. (symboles et fixnums vous donneront le même objet_id après des appels répétitifs) P>
L'utabilité n'a rien à voir avec elle (en fait, vous pouvez ajouter un état à un correctif).
Comportement par défaut vraiment bizarre pour Fixnum, en particulier étant donné qu'il a la méthode du clone, D.Class.Method_Definefin? (: Clone) == true
Je ne pense pas qu'il existe une liste formelle, au moins à moins que vous ne comptez en lecture de la source. La raison 2) ne fonctionne pas est à cause d'une optimisation appliquée aux fixations. Ils sont stockés / passés à l'intérieur de leurs valeurs réelles (ainsi sont vraies, fausses et nil) et non comme des pointeurs. La solution naïve consiste à avoir juste 42.cLone code> renvoyer le même
42 code>, mais ensuite le invariant
obj.clone.object_id! = Obj.object_id code> ne serait plus détenir,
42.Clone code> ne serait pas en train de cloner. p>
obj.clone.object_id! = obj.object_id code> être true et
obj.clone.object_id == obj.object_id code> pas toujours vrai sont différents sont différents. Que l'ancien ne veut pas dire ne signifie pas que ce dernier ne le fait pas.
fixnum est une classe spéciale donnée un traitement spécial par la langue. À partir du moment où votre programme lance, il existe exactement un correctif pour chaque nombre que la classe peut représenter, et ils ont une représentation spéciale qui ne prend aucun espace supplémentaire - de cette façon, les opérations de base des mathématiques ne sont pas allouées et négociantes mémoire comme un fou. Pour cette raison, il ne peut y avoir plus d'un 42. P>
Pour les autres, ils ont tous une chose en commun: ce sont des singletons. Il n'y a qu'une seule instance d'une classe Singleton par définition, tellement essayant de cloner c'est une erreur. P>
"Pour cette raison, il ne peut y avoir plus d'un 42.". Et pourquoi serait-il besoin d'être? C'est parfait.
Je ne sais toujours pas comment tester la clonabilité correctement, mais voici une façon très maladroite et diabolique de tester la clonablity à l'aide de la piégeage des erreurs: et voici comment vous pouvez cloner même le Non désagréable. Au moins pour les très rares classes que je l'ai fatiguée. P> Voici quelques tests d'échantillon: P> b = :b
puts "clonable? #{clonable? b}"
b = proc { b == "b" }
puts "clonable? #{clonable? b}"
b = [:a, :b, :c]
c = super_mega_clone(b)
puts "c: #{c.object_id}"
puts "b: #{b.object_id}"
puts "b == c => #{b == c}"
b.each_with_index do |value, index|
puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}"
end
b[0] = :z
puts "b == c => #{b == c}"
b.each_with_index do |value, index|
puts "[#{index}] b: #{b[index].object_id} c: #{c[index].object_id}"
end
b = :a
c = super_mega_clone(b)
puts "b: #{b.object_id} c: #{c.object_id}"
> clonable? false
> clonable? true
> c: 2153757040
> b: 2153757480
> b == c => true
> [0] b: 255528 c: 255528
> [1] b: 255688 c: 255688
> [2] b: 374568 c: 374568
> b == c => false
> [0] b: 1023528 c: 255528
> [1] b: 255688 c: 255688
> [2] b: 374568 c: 374568
> b: 255528 c: 255528
J'ai fait un Les première et troisième lignes indiquent que vous ne pouvez pas cloner Un singleton. p> La deuxième ligne fait référence à git grep "ne peut pas cloner" code> du code source de yarv et obtenu
rb_special_const_p (obj) code>. Mais cela va au-delà de mon ken. P> p>
rails semble étendre les classes que vous mentionnez avec une méthode "duplicable? ()". P>
Duplicable? () Est également défini dans le gemme ActiveSupport
Je veux vraiment savoir comment vous testez si une classe est clonable moi-même. Il semble que si une classe ne veuille pas se laisser clonée, il devrait faire de la méthode de clone privée qu'il hérite de l'objet afin que vous puissiez tester son existence uniquement sous Public_methods. Semble être bon sens pour moi.