2017-10-12 10 views
0

は、私は次のセットアップを持っていると言う:戻りコレクション

abstract class AbstractBaseClass { 

    // Some common attributes 

    AbstractBaseClass() { } 

    AbstractBaseClass(AbstractBaseClass orig) { 
     // Copy ctor impl 
    } 

    protected abstract AbstractBaseClass clone(); 
} 

class DerivedClassA extends AbstractBaseClass { 

    // Some specialized attributes 

    DerivedClassA() { } 

    DerivedClassA(DerivedClassA orig) { 
     super(orig); 
     // Copy ctor impl 
    } 

    List<DerivedClassB> subObjects = new ArrayList<>(); 

    protected DerivedClassA clone() { 
     return new DerivedClassA(this); 
    } 

} 

class DerivedClassB extends AbstractBaseClass { 

    // Some specialized attributes 

    DerivedClassB() { } 

    DerivedClassB(DerivedClassB orig) { 
     super(orig); 
     // Copy ctor impl 
    } 

    List<DerivedClassC> subObjects = new ArrayList<>(); 

    protected DerivedClassB clone() { 
     return new DerivedClassB(this); 
    } 

} 

// DerivedClassC implemented the same way 

今、私が含まれている科目の クローン与えられたリストの私の抽象基底クラスでの一般的なメソッドを実装したいのですが派生クラスのいずれかで、次のよう

abstract class AbstractBaseClass { 

    // Other stuff, see above 

    // Doesn't work because of type issues 
    protected <T> List<T> cloneList(List<? extends AbstractBaseClass> origList) { 
     if (origList == null) return null; 

     List<T> result = new ArrayList<>(); 
     for (AbstractBaseClass i: origList) { 
      result.add(i.clone()); 
     } 

     return result; 
    } 
} 

は、今私は、このメソッドを呼び出したい:

class DerivedClassA extends AbstractBaseClass { 

    // Other stuff 

    List<DerivedClassB> subObjects; 

    DerivedClassA(DerivedClassA orig) { 
     super(orig); 
     // Copy ctor impl 
     subObjects = cloneList(orig.subObjects); 
    }   

} 

の実装がAbstractBaseClassの場合、引数リストと同じ型のリストが返されるため、派生クラスに格納することができます。それについてどうすればいいのですか?

私は今のところ出ていましたが、私はそうのようなcloneList(...)を実装することができるということです。そして、

protected List<AbstractBaseClass> cloneList(List<? extends AbstractBaseClass> origList) { 
    // null check... 

    List<AbstractBaseClass> result = new ArrayList<>(); 
    for (AbstractBaseClass i: origList) { 
     result.add(i.clone()); 
    } 

    return result; 
} 

と私の派生クラスにキャストを使用します。

DerivedClassA(DerivedClassA orig) { 
    super(orig); 
    // Copy ctor impl 
    List<AbstractBaseClass> tmp = cloneList(orig.subObjects); 
    for (DerivedClassA i: tmp) { 
     subObjects.add((DerivedClassA) i); 
    } 
}  

しかし、これは実際にはありません私が満足しているのは、タイプのオブジェクトの複製されたコレクションを取得した後にキャストに依存しない汎用実装を1つ持っているからです。

+3

「ジェネリック」の実装を希望される場合、ジェネリックは – Stultuske

+0

このページをチェックしてください:https://docs.oracle.com/javase/tutorial/java/generics/index.html –

+0

*ご注意ください。クローン機能に重大な設計上の欠陥があります」http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4220218 –

答えて

0

あなたが変更される可能性があり、次の行:

abstract class AbstractBaseClass<T extends AbstractBaseClass<T>> 

protected List<T> cloneList(List<T> origList) { 
    if (origList == null) 
     return null; 

    List<T> result = new ArrayList<T>(); 
    for (T i : origList) { 
     result.add(i.clone()); 
    } 

    return result; 
} 

と派生クラス

class DerivedClassA extends AbstractBaseClass<DerivedClassA> 

、あなたがする必要はありません最後に

DerivedClassA(DerivedClassA orig) { 
    super(orig); 

    List<DerivedClassA> clonedList = cloneList(orig.subObjects); 
    subObjects.addAll(clonedList); 
} 

何かをキャストする。