2012-05-04 50 views
1

我在我的應用程序中有一個KillerSudoku類。在Ruby 1.9中複製一個對象和子對象

每個實例在@cells中都有很多單元,其中@zones等多個區域。

有沒有辦法輕鬆複製一個對象(數獨)複製所有的「子對象」,也就是說,我希望我的副本有我可以修改的單元格和區域,而無需修改以前的數獨?

回答

3

假設所有部分都serializable by Marshal,你想一個完全深克隆:

class Object 
    # This doesn't have to be on Object; it could be on KillerSudoku instead 
    def deep_clone 
    Marshal.load(Marshal.dump(self)) 
    end 
end 

看在行動:

class KillerSudoku 
    attr_accessor :cells 
end 

ks1 = KillerSudoku.new 
ks1.cells = ["one",2,3] 

ks2 = ks1.deep_clone 
ks2.cells.pop 
ks2.cells.first.reverse! 

p ks1.cells, ks2.cells 
#=> ["one", 2, 3] 
#=> ["eno", 2]   # New array with all instance values being uniq, too 

從文檔,上面不會有,如果您有任何工作以下在你的結構中:

  • 匿名ClassModule。這都涉及到系統(例如DirFile::StatIOFileSocket等)

  • MatchData的一個實例,DataMethodUnboundMethodProcThreadThreadGroupContinuation

  • 對象

  • 定義單例方法的對象


如上所示,這是一個真正的深層克隆,即使字符串變成新的實例。如果你想細胞和區的陣列被克隆,但都值仍然引用相同的對象,那麼你想定製什麼dupclone做用initialize_copy

class KillerSudoku 
    attr_accessor :cells 
    def initialize_copy(old) 
    self.cells = old.cells.dup 
    end 
end 

看在行動:

ks1 = KillerSudoku.new 
ks1.cells = ["one",2,3] 

ks2 = ks1.clone 
ks2.cells.pop 
ks2.cells.first.reverse! 

p ks1.cells, ks2.cells 
#=> ["eno", 2, 3] 
#=> ["eno", 2]   # New array that references all the same objects 
+0

我已經添加了一個替代實現,具體取決於你真正想克隆的深度。 – Phrogz

+2

有一種感覺,最好是定義'initialize_copy'方法來實現特定於類的重複行爲,而不是重寫'dup'或'clone'。他們都調用'initialize_copy'。這裏是關於這個問題的討論。 – Flexoid

+2

是的,抱歉=)[這是它](http://www.ruby-forum.com/topic/197273) – Flexoid