Médio Rust

Default e Display personalizado

Enunciado

Crie uma struct Rectangle com campos width: f64 e height: f64. Derive Debug, Clone e Default. Implemente manualmente Display para exibir o retângulo no formato Retângulo: largura x altura. No main, crie um retângulo padrão, clone-o, modifique o clone e imprima ambos usando Display e Debug.

Requisitos

  • A struct deve ter os campos width e height do tipo f64.
  • Os traits Debug, Clone e Default devem ser derivados.
  • O trait Display deve ser implementado manualmente.
  • O programa deve demonstrar o uso de Default, Clone, Display e Debug.

Código inicial

use std::fmt;

// Defina a struct Rectangle e derive Debug, Clone e Default

// Implemente Display para Rectangle

fn main() {
    // Crie um retângulo padrão
    // Clone-o e modifique as dimensões do clone
    // Imprima ambos com Display e Debug
}

Saída esperada

Retângulo padrão: 0 x 0
Debug do padrão: Rectangle { width: 0.0, height: 0.0 }
Retângulo clonado: 5 x 3
Debug do clonado: Rectangle { width: 5.0, height: 3.0 }
Ver dica

Para Display, implemente fmt::Display com write!(f, "Retângulo: {} x {}", self.width, self.height). Use Rectangle::default() para criar o padrão.

Mostrar solução
use std::fmt;

#[derive(Debug, Clone, Default)]
struct Rectangle {
    width: f64,
    height: f64,
}

impl fmt::Display for Rectangle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Retângulo: {} x {}", self.width, self.height)
    }
}

fn main() {
    let padrao = Rectangle::default();
    let mut clonado = padrao.clone();
    clonado.width = 5.0;
    clonado.height = 3.0;

    println!("Retângulo padrão: {}", padrao);
    println!("Debug do padrão: {:?}", padrao);
    println!("Retângulo clonado: {}", clonado);
    println!("Debug do clonado: {:?}", clonado);
}

Passo a passo

  1. Definimos Rectangle com campos f64 e derivamos Debug, Clone e Default.
  2. Implementamos Display manualmente, formatando a saída como Retângulo: largura x altura.
  3. No main, criamos padrao usando Rectangle::default(), que inicializa com zeros.
  4. Clonamos padrao para clonado com .clone() e alteramos seus campos.
  5. Imprimimos o retângulo padrão com Display ({}) e Debug ({:?}).
  6. Imprimimos o retângulo clonado da mesma forma.

Por que funciona

O derive gera automaticamente as implementações de Debug, Clone e Default porque todos os campos (f64) já implementam esses traits. Display não é derivável, então fornecemos nossa própria implementação. O clone cria uma cópia independente, permitindo modificar o clone sem afetar o original.

Erros comuns

  • Esquecer de derivar Clone e tentar usar .clone(): erro de compilação. Solução: adicionar Clone ao derive.
  • Tentar derivar Display: o compilador não permite; é necessário implementar manualmente.
  • Modificar o clone sem declarar mut: o compilador acusa que a variável não é mutável. Solução: declarar let mut clonado = ....

Outra forma de resolver

Se quiser um valor padrão diferente de zero, pode implementar Default manualmente em vez de derivar. Por exemplo, Rectangle { width: 1.0, height: 1.0 }. Isso é útil quando o padrão faz sentido para o domínio.

Saída esperada

Retângulo padrão: 0 x 0
Debug do padrão: Rectangle { width: 0.0, height: 0.0 }
Retângulo clonado: 5 x 3
Debug do clonado: Rectangle { width: 5.0, height: 3.0 }