Menu
Coddy logo textTech

Clone et Copy

Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 37 sur 61.

En Rust, lorsque vous assignez une valeur à une autre variable, la propriété (ownership) est généralement déplacée — la variable d'origine devient invalide. Cependant, deux traits standards modifient ce comportement : Clone et Copy.

Le trait Copy permet la copie bit à bit implicite. Lorsqu'un type implémente Copy, l'assigner à une autre variable crée une copie automatique au lieu de déplacer la propriété :

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 est copié, pas déplacé

println!("{}, {}", p1.x, p2.x);  // Les deux sont valides !

Le trait Clone fournit une copie profonde explicite via la méthode .clone(). Il est requis chaque fois que vous dérivez Copy, mais peut également être utilisé seul pour les types qui nécessitent une copie explicite :

let p3 = p1.clone();  // Copie explicite

Il existe une restriction importante : Copy ne peut être dérivé que pour les types dont tous les champs implémentent également Copy. Les types simples comme les entiers et les flottants sont Copy, mais String ne l'est pas — il gère la mémoire du tas (heap). Si votre struct contient un String, vous ne pouvez dériver que Clone, et non Copy.

TraitComportementUtilisation
CopyImplicite, automatiqueDonnées simples uniquement sur la pile
CloneExplicite via .clone()Toutes données duplicables

Pour les structures simples avec des champs primitifs, dériver les deux traits vous permet d'assigner librement des valeurs sans vous soucier de la possession (ownership).

challenge icon

Défi

Facile

Construisons un système de coordonnées qui démontre la différence entre les traits Copy et Clone ! Vous allez créer deux structs — l'une pouvant être copiée implicitement et l'autre nécessitant un clonage explicite — pour voir comment Rust gère la duplication différemment selon les traits que vous dérivez.

Vous organiserez votre code sur deux fichiers :

  • coordinates.rs : Définissez deux structs publiques qui représentent différents types de coordonnées :
    • GridPoint — avec des champs publics x et y (tous deux i32). Puisqu'elle ne contient que des types primitifs, dérivez à la fois Copy et Clone afin qu'elle puisse être copiée implicitement lors d'une affectation.
    • NamedLocation — avec un champ public name (String) et des champs x/y (i32). Puisqu'elle contient une String, vous ne pouvez dériver que Clone — pas Copy. Cette struct nécessitera des appels explicites à .clone() pour être dupliquée.
  • main.rs : Importez votre module coordinates et démontrez comment chaque struct se comporte différemment lors de la duplication. Créez des instances en utilisant les entrées fournies, puis montrez que :
    • Un GridPoint peut être assigné à une autre variable et les deux restent valides (copie implicite)
    • Une NamedLocation doit utiliser .clone() pour créer un duplicata tout en gardant l'original valide

Votre sortie doit afficher à la fois les valeurs originales et les valeurs copiées/clonées pour prouver que les deux variables sont valides après la duplication :

Original point: ({x}, {y})
Copied point: ({x}, {y})
Original location: {name} at ({x}, {y})
Cloned location: {name} at ({x}, {y})

Par exemple, avec les entrées 5, 10, et Home :

Original point: (5, 10)
Copied point: (5, 10)
Original location: Home at (5, 10)
Cloned location: Home at (5, 10)

Vous recevrez trois entrées : la coordonnée x (à parser en i32), la coordonnée y (à parser en i32), et le nom de l'emplacement.

Aide-mémoire

Le trait Copy permet la copie bit à bit implicite. Lorsqu'un type implémente Copy, l'assigner à une autre variable crée une copie automatique au lieu de transférer la propriété (move) :

#[derive(Copy, Clone)]
struct Point {
    x: i32,
    y: i32,
}

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 est copié, pas déplacé

println!("{}, {}", p1.x, p2.x);  // Les deux sont valides !

Le trait Clone permet la copie profonde explicite via la méthode .clone() :

let p3 = p1.clone();  // Copie explicite

Copy ne peut être dérivé que pour les types dont tous les champs implémentent également Copy. Les types simples comme les entiers et les flottants sont Copy, mais String ne l'est pas. Si votre structure contient une String, vous ne pouvez dériver que Clone, pas Copy.

TraitComportementUtilisation
CopyImplicite, automatiqueDonnées simples uniquement sur la pile (stack)
CloneExplicite via .clone()Toute donnée duplicable

Lors de la dérivation de Copy, vous devez également dériver Clone.

Essayez vous-même

mod coordinates;

use coordinates::{GridPoint, NamedLocation};

fn main() {
    // Lire les entrées
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let x: i32 = input1.trim().parse().expect("Invalid number");

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let y: i32 = input2.trim().parse().expect("Invalid number");

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let name = input3.trim().to_string();

    // TODO: Créer une instance de GridPoint avec x et y

    // TODO: Démontrer la copie implicite en assignant à une autre variable
    // (GridPoint implémente Copy, donc cela crée une copie automatiquement)

    // TODO: Afficher le point original et le point copié
    // Format : "Original point: ({x}, {y})"
    // Format : "Copied point: ({x}, {y})"

    // TODO: Créer une instance de NamedLocation avec name, x, et y

    // TODO: Démontrer le clone explicite (NamedLocation implémente uniquement Clone, pas Copy)
    // Utiliser .clone() pour créer un doublon

    // TODO: Afficher l'emplacement original et l'emplacement cloné
    // Format : "Original location: {name} at ({x}, {y})"
    // Format : "Cloned location: {name} at ({x}, {y})"
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Object Oriented Programming