今天在写程序时,发现有两个测试单独运行通过,但一起运行时第二个测试老挂。不用说,产生了依赖了么,找了半天,找到这么两句。
line_string = @@digital_lines[item][line_number] ... line_string.insert(1," ")
在irb中测试了一下,原来line_string只是一个指针呀,直接就把原始数据给修改了,这不就是鼎鼎大名的深浅拷贝么,汗~~~
没办法,在Google上面搜了一下,使用了Object中的dup方法,该方法类似于clone方法,返回一个相同值的全新对象,完成深拷贝,参考如下:
ruby-1.8.7-p330 :010 > a = "123" => "123" ruby-1.8.7-p330 :011 > b = a.dup => "123" ruby-1.8.7-p330 :012 > a.object_id => 2149191580 ruby-1.8.7-p330 :013 > b.object_id => 2149174920
可以看出,a和b时两个不同的对象,当然也就不存在相互影响的情况了。
大功告成了么?No, no, no. 好戏还没有结束,各位看官请往下看
ruby-1.8.7-p330 :062 > a = [["abc"]] => [["abc"]] ruby-1.8.7-p330 :063 > b = a.dup => [["abc"]] ruby-1.8.7-p330 :064 > a.object_id => 2149153820 ruby-1.8.7-p330 :065 > b.object_id => 2149144160 ruby-1.8.7-p330 :066 > a[0][0] = 1 => 1 ruby-1.8.7-p330 :067 > a => [[1]] ruby-1.8.7-p330 :068 > b => [[1]]
虽然调用了dup方法产生了不同的对象,但还是出现了浅拷贝的情况(当a[0][0]=1时,b的值也变了)。同样的情况还出现在Hash和我们自定义的类中。
想一想我们在C++和Java中时如何解决这个问题的?聪明的你一定想到了吧,既然系统自带的不给力,咱就自己写一个吧。实际上,已经有牛人写好了,我们直接用就行了,嘿嘿~~
参考如下:http://www.artima.com/forums/flat.jsp?forum=123&thread=40913
class Object def dclone case self when Fixnum,Bignum,Float,NilClass,FalseClass, TrueClass,Continuation klone = self when Hash klone = self.clone self.each{|k,v| klone[k] = v.dclone} when Array klone = self.clone klone.clear self.each{|v| klone << v.dclone} else klone = self.clone end klone.instance_variables.each {|v| klone.instance_variable_set(v, klone.instance_variable_get(v).dclone) } klone end end
还等什么,赶紧Command+C走吧~~~
PS:前文提到了dup和clone差不多,那Object中的dup和clone的区别是什么呢?
答案在这里,需要饭强哦(fan qiang是敏感词。。。)。