2012-05-09 102 views
1

我有一個抽象超類和一些派生類。
我想在派生類中它將創建的所有成員的智能副本衍生一個新的實例調用時創建的方法需要java繼承設計小技巧

createNew() 


所有對創建重要的成員都在抽象類中,因此代碼應該是相同的。
我可以在超類中編寫createNew()的實現嗎?

類似的東西

SonA sonA2 = sonA1.createNew() 
SonB sonB2 = sonB1.createNew() 

的ABS超應該做的實現,因爲該代碼是相同的。
謝謝。

回答

3

實現應該在抽象類和具體類之間進行拆分。

public abstract class AbstractSon { 
    protected abstract AbstractSon createNewImpl(); 
    public AbstractSon createNew() { 
     AbstractSon res = createNewImpl(); 
     res.name = "default name"; 
     return res; 
    } 
} 
public class Son1 extends AbstractSon { 
    protected AbstractSon createNewImpl() { 
     return new Son1(); 
    } 
} 
public class Son2 extends AbstractSon { 
    protected AbstractSon createNewImpl() { 
     return new Son2(); 
    } 
} 

您可以採用不同分裂的責任,以獲得精確的返回類型:您可以使用模板方法模式做

public abstract class AbstractSon { 
    protected void prepare(AbstractSon toPrepare) { 
     toPrepare.name = "default name"; 
    } 
} 
public class Son1 extends AbstractSon { 
    public Son1 createNew() { 
     Son1 res = new Son1(); 
     prepare(res); 
     return res; 
    } 
} 
public class Son2 extends AbstractSon { 
    public Son2 createNew() { 
     Son2 res = new Son2(); 
     prepare(res); 
     return res; 
    } 
} 
+0

是不是實際的C#代碼?你不應該使用「擴展」而不是:? – david99world

+0

@ david99world糟糕,你是對的 - 我最近做了太多的C#。現在已修復,謝謝! – dasblinkenlight

1

製作一個抽象方法,將用作您的createNew方法所使用的回調 - 並在每個子類中實現方法。 createNew可以是普通超類的具體方法,即使是final方法。提到的抽象方法將返回相應子類的新實例。

另一種方法是通過反思找出哪個類createNew被調用並基於此創建新實例。

+0

注意,在OP的示例'SonA.createNew()'和'SonB。 createNew()'有不同的返回類型。 – NPE

+0

@aix不一定,它可能是' createNew()'。它將用於特定的用例,但是在更復雜的表達式中它不會被使用。 –

1

你可以這樣寫代碼(使用反射:getClass().newInstance()獲得一個實際類的實例,而不是定義方法的類),但它有一些問題。例如,你打算從這種方法返回什麼?

您必須返回超類型,這意味着您必須爲每次調用進行投射。

通常的解決方案是定義在每個級別上定義的copy()方法。然後,你可以這樣做:

class SonA { 
    SonA createNew() { 
     SonA result = new SonA(); 
     this.copy(result); 
     return result; 
    } 

    void copy(SonA target) { 
     super.copy(target); 

     // copy my fields to target ... 
    } 
} 

您可能還需要閱讀有關copy constructors

1

一種可能性是出因子複製到一個單獨的方法,並調用從派生類createNew()

abstract class Base { 

    public abstract Base createNew(); 

    protected void populate(Base out) { 
    // copy the data from `this' to `out' 
    } 
} 

class Derived1 extends Base { 
    public Derived1 createNew() { 
    Derived1 ret = new new Derived1(); 
    populate(ret); 
    return ret; 
    } 
} 

class Derived1 extends Base { 
    public Derived2 createNew() { 
    Derived2 ret = new new Derived2(); 
    populate(ret); 
    return ret; 
    } 
}