2017-10-12 1 views
0

Dire que j'ai la configuration suivante:collection de retour du même paramètre en tant que paramètre de collecte d'entrée

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 

J'aimerais maintenant mettre en œuvre une méthode générique dans ma classe abstraite de base qui clones une liste donnée de sujets contenus dans l'une des classes dérivées:

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

maintenant, je veux appeler cette méthode comme suit:

class DerivedClassA extends AbstractBaseClass { 

    // Other stuff 

    List<DerivedClassB> subObjects; 

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

} 

Maintenant, ce que je m'attendais à ce que l'implémentation de cloneList(...) dans AbstractBaseClass renvoie une liste qui a le même type que la liste d'arguments, donc je peux les stocker dans mes classes dérivées. Comment pourrais-je m'y prendre?

Ce que j'ai trouvé à ce jour est que je peux mettre en œuvre cloneList(...) comme ceci:

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

et ensuite utiliser des moulages dans mes classes dérivées:

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

Mais ce n'est pas vraiment satisfaisant pour moi, puisque je voudrais avoir une implémentation générique qui ne repose pas sur le cast après avoir obtenu ma collection clonée d'objets de type AbstractBaseClass

+3

comme vous voulez une implémentation 'générique', les génériques pourraient nous valoir un coup d'oeil – Stultuske

+0

vérifiez cette page: https://docs.oracle.com/javase/tutorial/java/generics/index.html –

+0

* Soyez conscient * " La structure clone souffre de sérieuses failles de conception "http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4220218 –

Répondre

0

Vous pouvez modifier les lignes suivantes:

abstract class AbstractBaseClass<T extends AbstractBaseClass<T>> 

et

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

et la classe dérivée

class DerivedClassA extends AbstractBaseClass<DerivedClassA> 

et

DerivedClassA(DerivedClassA orig) { 
    super(orig); 

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

En fin de compte, vous n'avez pas besoin jeter n'importe quoi.