Desafio Rust
Enum com derive e Display condicional
Enunciado
Crie um enum Shape com variantes Circle { radius: f64 } e Rectangle { width: f64, height: f64 }. Derive Debug, Clone, PartialEq e Default (a variante padrão deve ser Circle { radius: 1.0 }). Implemente Display para Shape, mostrando "Círculo de raio X" ou "Retângulo de largura X e altura Y". No main, crie um vetor com várias formas, clone-o, compare elementos e imprima todos usando Display e Debug.
Requisitos
- O enum
Shapedeve ter as variantesCircleeRectanglecom os campos especificados. - Os traits
Debug,Clone,PartialEqeDefaultdevem ser derivados;Defaultdeve retornarCircle { radius: 1.0 }. Displaydeve ser implementado manualmente para formatar cada variante.- O programa deve demonstrar
Default,Clone,PartialEq,DisplayeDebugcom um vetor de formas.
Código inicial
use std::fmt;
// Defina o enum Shape e derive Debug, Clone, PartialEq, Default
// Implemente Default manualmente para Circle { radius: 1.0 }
// Implemente Display para Shape
fn main() {
// Crie um vetor de formas
// Clone o vetor
// Compare elementos
// Imprima tudo com Display e Debug
}
Saída esperada
Formas originais:
Círculo de raio 2.5
Retângulo de largura 3 e altura 4
Formas clonadas:
Círculo de raio 2.5
Retângulo de largura 3 e altura 4
Os vetores são iguais? true
Debug do primeiro clone: Circle { radius: 2.5 }
Debug do padrão: Circle { radius: 1.0 }
Ver dica
Para Default, implemente manualmente impl Default for Shape { fn default() -> Self { Shape::Circle { radius: 1.0 } } }. No Display, use match para tratar cada variante.
Mostrar solução
use std::fmt;
#[derive(Debug, Clone, PartialEq)]
enum Shape {
Circle { radius: f64 },
Rectangle { width: f64, height: f64 },
}
impl Default for Shape {
fn default() -> Self {
Shape::Circle { radius: 1.0 }
}
}
impl fmt::Display for Shape {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Shape::Circle { radius } => write!(f, "Círculo de raio {}", radius),
Shape::Rectangle { width, height } => write!(f, "Retângulo de largura {} e altura {}", width, height),
}
}
}
fn main() {
let formas = vec![
Shape::Circle { radius: 2.5 },
Shape::Rectangle { width: 3.0, height: 4.0 },
];
println!("Formas originais:");
for forma in &formas {
println!("{}", forma);
}
let clonadas = formas.clone();
println!("Formas clonadas:");
for forma in &clonadas {
println!("{}", forma);
}
println!("Os vetores são iguais? {}", formas == clonadas);
println!("Debug do primeiro clone: {:?}", clonadas[0]);
println!("Debug do padrão: {:?}", Shape::default());
}
Passo a passo
- Definimos o enum
Shapecom as variantesCircleeRectangle, cada uma com camposf64. - Derivamos
Debug,CloneePartialEq, mas nãoDefault, pois queremos um padrão personalizado. - Implementamos
Defaultmanualmente para retornarShape::Circle { radius: 1.0 }. - Implementamos
Displaycom ummatchque formata cada variante de acordo com o enunciado. - No
main, criamos um vetorformascom duas instâncias. - Imprimimos as formas originais usando
Display(laçofor). - Clonamos o vetor com
.clone()e imprimimos as formas clonadas. - Comparamos os vetores com
==(funciona porqueShapederivaPartialEq). - Imprimimos o
Debugdo primeiro clone e do valor padrão.
Por que funciona
O derive gera implementações para Debug, Clone e PartialEq porque todos os campos são f64, que já implementam esses traits. Default é implementado manualmente para escolher uma variante padrão. Display é manual para formatar cada variante de forma legível. O clone do vetor cria uma cópia profunda, e a comparação verifica igualdade campo a campo.
Erros comuns
- Tentar derivar
Defaulte obter a primeira variante com valores zero: se derivar, o padrão seriaCircle { radius: 0.0 }, mas queremos1.0. Solução: implementar manualmente. - Esquecer de derivar
PartialEqe tentar comparar vetores com==: erro de compilação. Solução: adicionarPartialEqao derive. - No
Display, não cobrir todas as variantes domatch: o compilador acusa match não exaustivo. Solução: tratar todas as variantes. - Usar
{}para imprimirShapesem implementarDisplay: erro de compilação. Solução: implementarDisplayou usar{:?}.
Outra forma de resolver
Se quiser que o padrão seja Rectangle { width: 0.0, height: 0.0 }, basta derivar Default e remover a implementação manual. No entanto, isso só funciona se a variante padrão for a primeira e todos os campos tiverem Default. Para maior controle, a implementação manual é preferível.
Saída esperada
Formas originais:
Círculo de raio 2.5
Retângulo de largura 3 e altura 4
Formas clonadas:
Círculo de raio 2.5
Retângulo de largura 3 e altura 4
Os vetores são iguais? true
Debug do primeiro clone: Circle { radius: 2.5 }
Debug do padrão: Circle { radius: 1.0 }