Une façon de dupliquer des objets non identiques est d'implémenter l'interface clonable et de remplacer ʻObject # clone`.
Cependant, lorsque je voulais dupliquer un objet en utilisant le type générique comme dans le code suivant, j'étais frustré car je ne pouvais pas accéder directement à ʻObject # clone`, donc je peux dupliquer l'objet même si j'utilise le type générique. J'ai décidé de concevoir diverses choses comme [^ best].
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> T cloneSample(T obj) {
return (T) obj.clone(); //Erreur de compilation (méthode de clonage invisible)
}
}
python
public interface CloneablePublicly<T> {
T clone();
}
Au lieu de ʻObject # clone`, j'ai créé une interface pour appeler une méthode de clonage de l'extérieur. Implémentons ceci pour une classe d'objets qui utilisent des types génériques.
Exemple d'implémentation
class Sample implements Cloneable, CloneablePublicly<Sample> {
int value;
public Sample(int value) {
this.value = value;
}
@Override public Sample clone() {
try {
return (Sample) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError(e);
}
}
}
Bien entendu, l'interface clonable est également implémentée en même temps. Si cela n'est pas implémenté, il lèvera une CloneNotSupportedException.
Après cela, si vous modifiez la méthode comme suit, par exemple, vous pouvez dupliquer l'objet à l'aide du type générique.
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> T cloneSample(T obj) {
if (obj instanceof Cloneable && obj instanceof CloneablePublicly) {
return ((CloneablePublicly<T>) obj).clone();
}
return null;
}
}
Exemple d'utilisation
Sample samp1 = new Sample(1);
Sample samp2 = GenericsSample.cloneSample(samp1);
System.out.println(samp1.value); // 1
System.out.println(samp2.value); // 1
System.out.println(samp1 == samp2); //false (duplication d'objets non identiques)
Si vous ne souhaitez pas retourner null, renvoyez le [^ cost] facultatif comme suit: Cela vous permet également de ne rien faire si vous ne pouvez pas dupliquer l'objet.
python
class GenericsSample {
@SuppressWarnings("unchecked")
static <T> Optional<T> cloneSample(T obj) {
return Optional.ofNullable(obj)
.filter(Cloneable.class::isInstance)
.filter(CloneablePublicly.class::isInstance)
.map(o -> ((CloneablePublicly<T>) obj).clone());
}
}
Exemple d'utilisation
Sample samp1 = new Sample(1);
GenericsSample.cloneSample(samp1).ifPresent(samp2 -> {
System.out.println(samp1.value); // 1
System.out.println(samp2.value); // 1
System.out.println(samp1 == samp2); //false (duplication d'objets non identiques)
});
// Sample samp1 = null;À ce moment-là, ne faites rien.
À partir du commentaire de @ saka1029, nous avons introduit l'héritage et l'implémentation d'interface en utilisant des paramètres de type de frontière. Je vous remercie!
Héritage de l'interface clonable
interface CloneablePublicly<T> extends Cloneable {
T clone();
}
De cette façon, vous n'avez pas à vous soucier d'implémenter l'interface clonable pour les classes d'objets qui utilisent des types génériques. ~~ J'ai complètement oublié la fonction d'héritage de l'interface. ~~
Exemple d'implémentation
class Sample implements CloneablePublicly<Sample> {
... //le même
}
python
class GenericsSample {
static <T extends CloneablePublicly<T>> T cloneSample(T obj) {
return Objects.isNull(obj) ? null : obj.clone();
}
}
Les paramètres limites sont utilisés pour assurer la sécurité du type, éliminant le besoin d'une inspection manuelle de la fonte. La ligne facultative est terminée.
python
class GenericsSample {
static <T extends CloneablePublicly<T>> Optional<T> cloneSample(T obj) {
return Optional.ofNullable(obj).map(CloneablePublicly::clone);
}
}
[^ best]: J'ai beaucoup cherché, mais je n'ai trouvé aucun matériel qui avait l'air bien, alors je l'ai fait moi-même. Nous vous prions de nous excuser pour tout inconvénient, mais nous vous serions reconnaissants de bien vouloir nous enseigner la méthode ou les suggestions des meilleures pratiques. [^ Coût]: Selon "Effective Java 3rd Edition", il est coûteux d'utiliser fréquemment Optionnel, il peut donc être préférable de ne pas l'utiliser si vous êtes préoccupé par les performances.
Recommended Posts