Todavía no sé cómo probar clonability correctamente, pero esto es una manera muy torpe, mal para la prueba de clonablity mediante la interceptación de errores:
def clonable?(value)
begin
clone = value.clone
true
rescue
false
end
end
Y aquí es cómo se puede clonar incluso el unclonable. Al menos para las pocas clases con las que lo he cansado.
def super_mega_clone(value)
eval(value.inspect)
end
Aquí hay algunas pruebas de muestra:
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
que realmente quieren saber cómo se prueba si una clase es cloneable mí mismo. Parece que si una clase no quiere permitirse clonar, debe hacer privado el método de clonación que hereda de Object para que pueda probar su existencia solo bajo public_methods. Parece sentido común para mí. –