Move, Copy et Clone
Move
Lorsqu'une fonction désire obtenir l'ownership d'une variable.
On vient déplacer la variable du contexte appelant vers le contexte appelé.
Prenons une structure Toto.
On déclare une fonction function_1
, celle-ci ne fait rien à part prendre l'ownership de la variable passé en paramètre.
On déclare dans un main, une variable toto
de type Toto.
Lorsque l'on passe en paramètre la variable toto
à la fonction function_1
, on dit que l'on déplace ou move la variable vers function_1
.
C'est comme si vous aviez un carton dans une maison 1 et que vous le déplaciez dans une maison 2.
Et donc très logiquement si on réitère l'expérience, ça coince.
Pourquoi, ça coince ?
Et bien, votre carton n'a pas le don d'ubiquité (ce mot est cadeau pour vous 😁). Autrement dit, elle ne peut pas à la fois être dans la maison main
et dans la maison function_1
.
Donc si les déménageurs arrivent, ils ne trouveront pas le carton dans la maison main
! Et ne pourront pas le déplacer vers la maison function_1*
Clone
Pour remédier à cette situation, nous allons devoir implémenter un trait.
Celui-ci ce nomme Clone
.
Il ne dispose que d'une fonction à implémenter.
Ce trait renvoit une duplication de lui-même, cela impliquant que chaque champ de la structure qui l'implémente doivent eux-aussi être clonable.
Pour notre structure Toto ce n'est pas un soucis.
On déréférence le self et on renvoit une copie.
Un clone est déclenché de manière consciente et explicite par le développeur.
Si ce que vous clonez est gros, cela peut avoir des conséquences sur les performances de votre programme.
Chaque
.clone()
aura pour effet de dupliquer chaque valeur du tableau.Si les opérations de clonage sont trop fréquentes, cela risque d'engorger votre programme.
Il est possible de se passer de l'implémentation du trait Clone
en passant par la dérivation.
;
Nous avons maintenant des armes pour travailler. 😁
Il faut voir le clone comme une machine qui prend en entré une variable clonable, en réalise une deuxième version exacte et rend la première version.
Notre scénario avec les déménageurs va donc se dérouler en deux temps:
Premièrement, on clone le carton toto
en un deuxième carton toto_clone
.
Puis on demande à l'équipe 1 de déménager le carton étiqueté toto_clone
et à l'équipe 2 de déménager le carton étiqueté toto
.
Chaque équipe trouve son carton, tout le monde est content. 😀
Comme tout à l'heure,
toto
ayant été déplacé dansfunction_1*
, il n'existe plus dansmain
.Cela implique qu'il n'est plus clonable dans
main
et n'est pas déplaçable dans une troisième maisonfunction_1**
Copy
Il existe un deuxième mécanisme que nous avons d'ailleurs utilisé sans nous en rendre compte, il s'agit de la copie.
Pour pouvoir bénéficier de cette capacité une variable doit être copiable.
Cette attribut est fourni par le trait Copy
.
Le trait Copy
est un super trait de Clone
. Cela implique que pour implémenter Copy
une structure doit obligatoirement implémenter Clone
.
Le trait Copy
est ce qu'on appelle un Marker, un trait sans implémentation.
;
Il est également possible de passer la dérivation.
;
Celle-ci est fourni par le langage et ne peut pas être défini par le développeur.
Les types primimitifs sont tous copiables. A l'exeception des chaîne de caractères qui sont en fait des références.
Une structure composée de types primitifs est donc copiable.
Quel super-pouvoirs cela nous octroie ?
Et bien, plus besoin de demander explicitement un clone via .clone()
tout se fait magiquement !
Ce qui implique que l'on peut écrire ceci
Si on reprend la scenette des déménageurs, c'est comme si à chaque fois qu'on prenait un carton, celui-ci se dupliquait de lui-même.
Ce qui permet à chaque maison function_1
d'avoir sa propre copie de toto
.
Autre avantage, le toto
originel ne quitte jamais la maison main
!
Il est donc possible de déménager le carton toto
autant de fois que l'on le désire.
La copie étant implicite, il est possible de copier de grandes quantitée de données sans s'en rendre compte !
Conclusion
Si une fonction désire l'ownership d'une variable il faut déplacer la variable du contexte appellant vers le contexte appelé.
Une fois qu'une variable est déplacée dans le contexte appelé, elle n'est plus disponible dans le contexte appellant.
Pour conserver la disponibilité d'une variable dans le contexte appellant, il faut dupliquer la variable.
Soit via un Clone
expicite.
Soit via un Copy
implicite.
Toute variable copiable est clonable mais l'inverse n'est pas vrai.
Ce travail est sous licence CC BY-NC-SA 4.0.