Hai una delle tre scelte:
- avere un metodo su
IAnimal
per clonare profondamente l'oggetto (usato da librerie come le interfacce DOM come Node.cloneNode(boolean)
)
- Creare un costruttore di copie in tutte le implementazioni di
IAnimal
che prende il tipo concreto e ne fa un requireme nt nel contratto di interfaccia, quindi utilizzare la reflection per accedervi
- Creare una copia factory che copierà ogni implementazione manualmente
- Utilizzare una libreria di terze parti che implementa la clonazione profonda per i propri contratti, ad esempio no-args costruttori, campi non finali, classi
Serializable
, ecc., Come quelli elencati here
Metodo Copy
Per # 1, fare qualcosa di simile:
public interface IAnimal {
IAnimal cloneDeep();
}
Implementare che nelle vostre tipi concreti, quindi richiamare tale metodo per copiare:
this.pet = pet.cloneDeep();
Quindi documentare il requisito nell'interfaccia, ad esempio s omething lungo le linee di:
Implementazioni di questa interfaccia deve restituire un oggetto che non ==
è a questa istanza, e deve essere profondamente clonato in modo che la manipolazione di questo oggetto non comporti la manipolazione di quello restituito e viceversa.
Le implementazioni dovranno seguire questo contratto per essere conformi all'interfaccia, ma questo non verrà applicato in fase di compilazione.
Copia Constructor
tenta di accedere a un costruttore di copia riflessivo, quindi affermare che un costruttore di copia è richiesto in tutte le implementazioni concrete nel interfaccia, che diventa parte integrante del contratto di interfaccia. Ogni implementazione sarebbe quindi simile a questa:
public class Dog implements IAnimal {
private String name;
public Dog(Dog dog) {
this.name = dog.name;
}
}
E poi tutto ciò che serve è un unico metodo per copiare ogni implementazione:
public static <A extends IAnimal> A copy(A animal) {
Class<?> animalType = animal.getClass();
// This next line throws a number of checked exceptions you need to catch
return (A) animalType.getConstructor(animalType).newInstance(animal);
}
Uno si dispone di questo, aggiungere una dichiarazione in tal senso nella vostra interfaccia di documentazione:
le implementazioni di questa interfaccia deve definire un costruttore di copia che prende un argomento dello stesso tipo o supertipo della loro classe. Questo costruttore deve fare una copia profonda dell'argomento in modo tale che la manipolazione di questo oggetto non porti alla manipolazione di quella restituita e viceversa.
Ancora, questo è il runtime applicato. Il metodo copy
in alto genera errori NoSuchMethodException
quando il costruttore non esiste.
copia di fabbrica
Questa prende il IAnimal
e utilizza instanceof
decidere quale metodo per passare a, come:
public static IAnimal copyAnimal(IAnimal animal) {
if (animal instanceof Dog)
return copyDog((Dog) animal);
if (animal instanceof Cat)
return copyCat((Cat) animal);
//...
else
throw new IllegalArgumentException("Could not copy animal of type: "
+ animal.getClass().getName());
}
Quindi eseguire la copia in profondità nelle copy
metodi per ogni tipo manuale .
Se si desidera una copia profonda, è necessario implementare anche un costruttore di copia in Animal. – alfasin
Non è possibile semplicemente implementare un costruttore di copia in Animal. In questo caso hai IAnimal, un'interfaccia. Quindi dovresti sapere quale classe concreta hai bisogno di istanziare. – Mene