2013-04-03 38 views
0

當在網絡中搜索多種可能性時如何製作對象的深層副本時,我發現solution聲稱可以解決許多問題,例如,clone()方法不可能克隆final字段。該解決方案結合使用clone()裏面執行受保護的拷貝構造函數,基本上是這樣的(例如,從引用的頁面複製):使用新的關鍵字和複製構造函數代替super.clone的Java克隆()方法

public class Person implements Cloneable 
{ 
    private final Brain brain; // brain is final since I do not want 
           // any transplant on it once created! 
    private int age; 

    public Person(Brain aBrain, int theAge) 
    { 
     brain = aBrain; 
     age = theAge; 
    } 

    protected Person(Person another) 
    { 
     Brain refBrain = null; 
     try 
     { 
      refBrain = (Brain) another.brain.clone(); 
      // You can set the brain in the constructor 
     } 
     catch(CloneNotSupportedException e) {} 
     brain = refBrain; 
     age = another.age; 
    } 

    public Object clone() 
    { 
     return new Person(this); 
    } 

    … 
} 

Brainclone()方法可以以類似的方式來實現。

基於documentation of the clone() method,似乎這個方法的所有「契約」不是絕對的要求,而且「返回的對象應該通過調用super.clone()獲得」僅僅是一個約定。

那麼,這個實現實際上是不正確的?爲什麼?

如果它是正確的,爲什麼它沒有成爲設計模式?這有什麼缺點?

感謝,切赫

+0

我不明白爲什麼不簡單地使用「新人(this.brain,this.age)」(如果屬性是最終的)或「新人(this.brain.clone(),this.age)在其他case –

+0

clone()'已經足夠的了,你應該只是在任何地方使用拷貝構造函數,並且完全停止編寫'clone'方法 –

+0

我從來沒有理解過爲什麼你需要它們,你需要在C++中拷貝構造函數,因爲編譯器生成調用有時甚至需要自己編寫它們,最終這是因爲默認的C++參數語義是object-by的值,但在近16年的Java中,我從未使用clone()或copy構造函數任何嚴肅的代碼 – EJP

回答

1

正試圖通過實施可複製的接口,但不遵循克隆的推薦合約克隆。

你基本上是使用拷貝構造函數創建新的對象,我的問題是爲什麼你需要實現可複製?

如果您正在實施可複製,那麼您必須遵守合同。當你在克隆方法中使用複製構造函數時,我不會推薦這種方法,因爲它的子類的克隆不會是子類的對象,而是一個Person類的對象。

還要指出的是,使用複製構造函數代替cloneable接口是更多面向對象的方法。

+0

我的問題的一個部分是,我完全不清楚clone()和Cloneable的合約是什麼。在文檔中,所有看起來像他們合同的東西都會因爲「但它不是一個絕對的要求」或類似的東西而被削弱。那麼,clone()和Clonable的實際合約是什麼? 關於「基本上使用複製構造函數時爲什麼需要clone()」的問題:因爲我需要多態克隆行爲。在編寫代碼的時候,我不知道應該實例化的實際類是什麼。 – Posa

+0

Ok同意它不是一個絕對的要求,但是當人們要使用你的代碼時,他們會期望在這些線上[這就是爲什麼我們有合同]。其次,它如何幫助混合克隆和複製構造函數?我認爲這隻會讓你的事情變得複雜。你可以通過複製構造函數來實現多態行爲,但我只是說它不會與克隆一起使用,因爲它只會造成混淆。 – Lokesh

+0

如何製作一個複製構造函數多態?它對每個班級都有不同的名稱。你能給我一個簡單的例子嗎? – Posa

0

那麼,這個實現實際上是不正確?爲什麼?

因爲刪除了CloneNotSupportedException,所以不安全。

如果大腦不可克隆新人將沒有大腦:) 如果您的對象結構中有一個對象沒有控制(無法訪問源),該怎麼辦?

爲什麼它沒有成爲一個設計模式

因爲並不是所有對象都剛剛從類似的物體被克隆。通常,有一些環境對象更好地知道這個特定的新對象看起來像什麼,而不是它現有的鄰居對象。

0

此方法(在事實CloneNotSupportedException被丟棄旁)的缺點是,如果子類調用super.clone()他們將獲得的Person一個實例,而不是他們自己的類的實例,因爲他們可能希望。

你的方法是確定的,如果你知道子類不會依賴Object.clone()(或如果沒有子類)

+0

所以,你基本上說我不應該將clone()和Clonable的方法與不同的東西混合在一起,因爲我不能確保我的類的用戶會像我一樣使用相同的方法,對吧? – Posa

+0

是的,當你實現clone()時,你通常通過調用super.clone()來做到這一點。如果你不這樣做,確保它是有據可查的,因爲子類也無法做到這一點。 – WilQu

相關問題