Je ne sais toujours pas comment tester clonabilité correctement, mais voici un très maladroit, mauvais chemin pour tester clonablity en utilisant la récupération d'erreur:
def clonable?(value)
begin
clone = value.clone
true
rescue
false
end
end
Et voici comment vous pouvez cloner même le inclonable. Au moins pour les quelques classes avec lesquelles je l'ai fatigué.
def super_mega_clone(value)
eval(value.inspect)
end
Voici quelques tests d'échantillons:
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
Je veux vraiment savoir comment tester si une classe est cloneable moi-même. Il semble que si une classe ne veut pas se permettre d'être clonée, elle devrait rendre privée la méthode clone héritée de l'objet afin que vous puissiez tester son existence uniquement sous public_methods. On dirait du bon sens pour moi. –