2017-06-28 153 views
0

比方說,我有一個類Child它擴展另一個類,Parent在Java中,我可以創建「基於」超類實例的子類實例嗎?

public class Parent { 
    private String value; 
    public Parent() { } 
    public String getValue() { return this.value; } 
    public void setValue(String value) { this.value = value; } 
} 

public class Child extends Parent { 
    private String anotherValue; 
    public Child() { super(); } 
    public String getAnotherValue() { return this.anotherValue; } 
    public void setAnotherValue() { this.anotherValue = anotherValue; } 
} 

現在,對於類Parent的任何實例parent,並希望構建類的實例childChild使得物體child延伸對象parent,即在這種情況下,child.getValue().equals(parent.getValue())。要做到這一點

的方法之一,是一個構造函數添加到Child如下:

public Child(Parent parent) { 
     this.setValue(parent.getValue()); 
    } 

這做工作,但它可以挑剔的,如果超類是更復雜的,更重要的是,超類隨着時間的推移而演變,這個構造函數應該不斷地更新,這可以被遺忘,或多或少造成災難性的影響。

它也可以用反射來完成,這可能是一種矯枉過正。

所以我不知道是否有任何Java本地方式來做到這一點:創建一個子類的實例,並複製超類的實例的所有屬性。這是一種與鑄造相反的方式。

+0

本身,我會反思這樣做。在一個真實的項目中,我會使用推土機(實際上是通過反射來實現的,但是比自己做的更好) –

+0

您的用例是什麼? – ControlAltDel

+0

很難知道爲什麼你需要這個,但也許你可以使用上限通配符?例如,如果您有一個方法需要列表,並且您想要將其更改爲也取得子列表,則可以將該參數重寫爲List <?繼承Parent>。 https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html – Dziugas

回答

0

「我不知道是否有任何Java本機的方式來做到這一點:創建一個子類的實例,並複製所有實例的超類屬性」

沒有想到的,但你應該考慮你想要做什麼更難一點。你可以在Parent中添加一個拷貝構造函數或者使用clone。

class Parent { 
    String type; 
    public Parent(Parent p) { this.type = p.type; } 
} 

class Child extends Parent { 
    public Child(Parent p) { super(p); } 
} 

或者你也可以在兒童

class Parent { 
    String type; 
    public copyInstance(Parent p) { this.type = p.type; } 
} 

class Child extends Parent { 
    static Child newInstance(Parent p) { Child c = new Child(); c.copyInstance(p); return c; } 
} 

或其他東西一樣,創造一個靜態newInstance()方法。總之,我不得不問你爲什麼要問Child知道Parent

+1

要求子類「Child」知道父類'Parent',正是我試圖避免的!並且你的解決方案都可以工(順便說一句,如果我可以編輯你的答案,我會在'class Child'的聲明中添加'extends Parent'。) – shn

1

不,有沒有內置支持自動做到這一點。如果要複製字段值,常見圖案是創建拷貝構造函數既爲ParentChild類:如果你想只從超級複製領域

public class Parent { 
    public int a; 
    public String s; 

    public Parent(Parent src) { 
     this.a = src.a; 
     this.s = src.s; 
    } 

    // +init-constructor 
} 

public class Child extends Parent { 
    public double d; 

    public Child(Child src) { 
     super(src); 
     this.d = src.d; 
    } 

    // +init-constructor 
} 

編輯

Parent I類將再增加拷貝構造函數只複製父字段:

public class Child extends Parent { 
    // +fields 

    // +copy-constructor Child(Child src) 

    public Child(Parent src) { 
     super(src); 
    } 

    // +init-constructor 
} 

所以正確的構造函數將根據實例的類型進行選擇。

Parent p = new Parent(1, "a"); 
Child c = new Child(1, "a", 2.0); 

Child pCopy = new Child(p); 
Child cCopy = new Child(c); 

注意,你也可以明確地向上轉換子實例,以父類型的情況下,你只想父領域從孩子複製:

Child c = new Child(1, "a", 2.0); 
Child pCopy = new Child((Parent) c); 

如果要複製領域已我會做一些類似於你在@KarlNicholas的回答中看到的東西。

+0

因此,對於子類而不是複製構造函數,我需要一個構造函數,如'public Child(Parent src){super(src ); '',對吧? (因爲我只有一個'Parent'的實例,我想在其中構建一個'Child'的實例。) – shn

+0

@shn請參閱我的編輯。 – matoni

0

是的,這是java的一個缺點。基本上我們在這裏討論克隆。 Java沒有內置在該語言中的強大的對象克隆機制。你必須使用像序列化/反序列化這樣的黑客。

,你可以在你的情況怎麼辦:

class Child { 
private Parent parent; 

public Child(Parent p) { 
// reference - carefully! If Parent were immutable, this would be safe, otherwise, you need a copy constructor 
this.parent = p; 
} 
} 
+0

不幸的是,在手頭的情況下,我沒有選擇繼承_composition ,否則,這將是一個非常可行的解決方案... – shn

+0

你應該總是儘可能在你的設計中儘可能地考慮繼承。但是,是的,這是一個典型的繼承例子。 – ACV