Menu
Coddy logo textTech

Clone y Copy

Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 37 de 61.

En Rust, cuando asignas un valor a another variable, la propiedad normalmente se mueve: la variable original deja de ser válida. Sin embargo, dos traits estándar cambian este comportamiento: Clone y Copy.

El trait Copy permite la copia implícita bit a bit. Cuando un tipo implementa Copy, asignarlo a otra variable crea una copia automática en lugar de mover la propiedad:

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

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 se copia, no se mueve

println!("{}, {}", p1.x, p2.x);  // ¡Ambos son válidos!

El trait Clone proporciona una copia profunda explícita mediante el método .clone(). Es obligatorio siempre que derives Copy, pero también puede usarse por sí solo para tipos que necesitan una copia explícita:

let p3 = p1.clone();  // Copia explícita

Hay una restricción importante: Copy solo se puede derivar para tipos cuyos campos también implementan Copy. Los tipos simples, como los enteros y los números de coma flotante, son Copy, pero String no lo es. Gestiona la memoria del montón. Si tu estructura contiene un String, solo puedes derivar Clone, no Copy.

TraitComportamientoUso
CopyImplícito, automáticoDatos simples solo en la pila
CloneExplícito mediante .clone()Cualquier dato duplicable

Para las estructuras simples con campos primitivos, derivar ambos rasgos te permite asignar valores libremente sin preocuparte por la propiedad.

challenge icon

Desafío

Fácil

¡Construyamos un sistema de coordenadas que demuestre la diferencia entre los traits Copy y Clone! Crearás dos estructuras, una que se pueda copiar implícitamente y otra que requiera una clonación explícita, para ver cómo Rust gestiona la duplicación de manera diferente según los traits que derives.

Organizarás tu código en dos archivos:

  • coordinates.rs: Define dos estructuras públicas que representan distintos tipos de coordenadas:
    • GridPoint: con campos públicos x e y (ambos i32). Como solo contiene tipos primitivos, deriva tanto Copy como Clone para que se pueda copiar implícitamente al asignarlo.
    • NamedLocation: con un campo público name (String) y campos x/y (i32). Como contiene un String, solo puedes derivar Clone, no Copy. Esta estructura requerirá llamadas explícitas a .clone() para duplicarse.
  • main.rs: Incorpora tu módulo de coordenadas y demuestra cómo se comporta cada estructura de manera diferente al duplicarla. Crea instancias usando las entradas proporcionadas y, después, muestra que:
    • Un GridPoint se puede asignar a otra variable y ambas siguen siendo válidas (copia implícita)
    • Un NamedLocation debe usar .clone() para crear un duplicado mientras el original sigue siendo válido

Tu salida debe mostrar tanto los valores originales como los copiados/clonados para demostrar que ambas variables son válidas después de la duplicación:

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

Por ejemplo, con las entradas 5, 10 y Home:

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

Recibirás tres entradas: la coordenada x (analízala como i32), la coordenada y (analízala como i32) y el nombre de la ubicación.

Pruébalo tú mismo

mod coordinates;

use coordinates::{GridPoint, NamedLocation};

fn main() {
    // Leer entradas
    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: Crea una instancia de GridPoint con x e y

    // TODO: Demuestra la copia implícita asignando a otra variable
    // (GridPoint implementa Copy, por lo que esto crea una copia automáticamente)

    // TODO: Imprime el punto original y el copiado
    // Format: "Original point: ({x}, {y})"
    // Formato: "Copied point: ({x}, {y})"

    // TODO: Crea una instancia de NamedLocation con name, x e y

    // TODO: Demuestra el clone explícito (NamedLocation solo implementa Clone, no Copy)
    // Usa .clone() para crear un duplicado

    // TODO: Print original and cloned location
    // Format: "Original location: {name} at ({x}, {y})"
    // Format: "Cloned location: {name} at ({x}, {y})"
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de Rust online