Which Ruby classes support .clone?

前端 未结 6 947
自闭症患者
自闭症患者 2021-01-05 02:48

Ruby defines #clone in Object. To my suprise, some classes raise Exceptions when calling it. I found NilClass, TrueCla

6条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-05 03:00

    I still don't know how to test for clonability properly but here's a very clunky, evil way to test for clonablity using error trapping:

    def clonable?(value)
      begin
        clone = value.clone
        true
      rescue
        false
      end
    end
    

    And here's how you can clone even the unclonable. At least for the very few classes I've tired it with.

    def super_mega_clone(value)
      eval(value.inspect)
    end
    

    Here's some sample testing:

    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
    

提交回复
热议问题