2012-05-09 4 views
1

私は抽象スーパークラスといくつかの派生クラスを持っています。
私は、派生クラスで呼び出されたとき、それは、そのメンバーのすべてのスマートコピーと派生の新しいインスタンスを作成します方法Java継承の設計のヒントが必要です

createNew() 

を作成したいです。
作成に重要なメンバーはすべて抽象クラスであり、コードは同じである必要があります。
スーパークラスにcreateNew()の実装を記述することはできますか?コードが同じであるため、その

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

腹筋のスーパーのような

何かが実装を行う必要があります。ありがとうございます。
ありがとうございます。

答えて

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(); 
    } 
} 

:あなたはTemplate Methodパターンを使用してそれを行うことができます。このコードを書くことができ

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#コードではありませんか? :ではなく、 "extends"を使うべきですか? – david99world

+0

@ david99worldおっと、そうです - 最近C#をやっています。これは修正されました。ありがとう! – dasblinkenlight

1

createNewメソッドで使用されるコールバックとして機能する抽象メソッドを作成し、各サブクラスにメソッドを実装します。createNewはコンクリートでもよく、普通のスーパークラスのfinalメソッドです。前述の抽象メソッドは、それぞれのサブクラスの新しいインスタンスを返します。

代替アプローチは、どのクラスが呼び出されたかを反映して調べ、それに基づいて新しいインスタンスを作成することです。

+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; 
    } 
} 
関連する問題