Menu
Coddy logo textTech

Clone e Copy

Parte da seção Programação Orientada a Objetos do Journey de Rust da Coddy. Lição 37 de 61.

Em Rust, quando você atribui um valor a outra variável, a propriedade normalmente é movida: a variável original se torna inválida. No entanto, duas traits padrão alteram esse comportamento: Clone e Copy.

A trait Copy possibilita a cópia implícita bit a bit. Quando um tipo implementa Copy, atribuí-lo a outra variável cria uma cópia automática em vez de mover a propriedade:

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

let p1 = Point { x: 10, y: 20 };
let p2 = p1;  // p1 é copiado, não movido

println!("{}, {}", p1.x, p2.x);  // Ambos são válidos!

A trait Clone fornece cópia profunda explícita por meio do método .clone(). Ela é obrigatória sempre que você deriva Copy, mas também pode ser usada sozinha para tipos que precisam de cópia explícita:

let p3 = p1.clone();  // Cópia explícita

Há uma restrição importante: Copy só pode ser derivado para tipos cujos campos também implementam Copy. Tipos simples, como inteiros e números de ponto flutuante, são Copy, mas String não é. Ele gerencia memória no heap. Se sua struct contiver uma String, você só poderá derivar Clone, não Copy.

TraitComportamentoUso
CopyImplícito, automáticoDados simples apenas na pilha
CloneExplícito via .clone()Qualquer dado duplicável

Para structs simples com campos primitivos, derivar ambas as traits permite que você atribua valores livremente sem se preocupar com a propriedade.

challenge icon

Desafio

Fácil

Vamos criar um sistema de coordenadas que demonstre a diferença entre as traits Copy e Clone! Você criará duas structs, uma que pode ser copiada implicitamente e outra que exige clonagem explícita, para ver como Rust trata a duplicação de maneira diferente com base nas traits derivadas.

Você organizará seu código em dois arquivos:

  • coordinates.rs: Defina duas structs públicas que representam diferentes tipos de coordenadas:
    • GridPoint: com campos públicos x e y (ambos i32). Como ela contém apenas tipos primitivos, derive tanto Copy quanto Clone para que possa ser copiada implicitamente quando atribuída.
    • NamedLocation: com name público (String) e campos x/y (i32). Como ela contém uma String, você só pode derivar Clone, não Copy. Essa struct exigirá chamadas explícitas a .clone() para ser duplicada.
  • main.rs: Importe seu módulo de coordenadas e demonstre como cada struct se comporta de maneira diferente quando duplicada. Crie instâncias usando as entradas fornecidas e, em seguida, mostre que:
    • Um GridPoint pode ser atribuído a outra variável e ambas continuam válidas (cópia implícita)
    • Um NamedLocation deve usar .clone() para criar uma duplicata mantendo o original válido

Sua saída deve mostrar os valores original e copiado/clonado para provar que ambas as variáveis são válidas após a duplicação:

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

Por exemplo, com as entradas 5, 10 e Home:

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

Você receberá três entradas: a coordenada x (analise como i32), a coordenada y (analise como i32) e o nome da localização.

Experimente você mesmo

mod coordinates;

use coordinates::{GridPoint, NamedLocation};

fn main() {
    // Ler 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: Crie uma instância de GridPoint com x e y

    // TODO: Demonstre a cópia implícita atribuindo a outra variável
    // (GridPoint implementa Copy, então isso cria uma cópia automaticamente)

    // TODO: Imprima o ponto original e o copiado
    // Format: "Original point: ({x}, {y})"
    // Formato: "Copied point: ({x}, {y})"

    // TODO: Crie uma instância de NamedLocation com name, x e y

    // TODO: Demonstre o clone explícito (NamedLocation só implementa Clone, não Copy)
    // Use .clone() para criar uma duplicata

    // TODO: Print original and cloned location
    // Format: "Original location: {name} at ({x}, {y})"
    // Format: "Cloned location: {name} at ({x}, {y})"
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Rust online