Fácil Rust

Trait Forma com método padrão

Enunciado

Crie uma trait Forma com o método obrigatório area(&self) -> f64 e um método padrão descricao(&self) -> String que retorne "Área: X", onde X é a área formatada com {:.2}. Implemente Forma para Retangulo { largura: f64, altura: f64 } e imprima a descrição de um retângulo 3.0 x 4.0.

Requisitos

  • A trait Forma tem area obrigatória e descricao com corpo padrão.
  • Retangulo implementa Forma calculando largura * altura.
  • main cria um retângulo 3.0 x 4.0 e imprime descricao().

Código inicial

trait Forma {
    // TODO: método area e método padrão descricao
}

struct Retangulo {
    largura: f64,
    altura: f64,
}

// TODO: impl Forma for Retangulo

fn main() {
    // TODO: criar retângulo e imprimir descricao()
}

Saída esperada

Área: 12.00
Ver dica

No método padrão use format!("Área: {:.2}", self.area()); o {:.2} limita a duas casas decimais.

Mostrar solução
trait Forma {
    fn area(&self) -> f64; // obrigatório

    // método padrão: usa area(), então é herdado por quem implementa
    fn descricao(&self) -> String {
        format!("Área: {:.2}", self.area())
    }
}

struct Retangulo {
    largura: f64,
    altura: f64,
}

impl Forma for Retangulo {
    fn area(&self) -> f64 {
        self.largura * self.altura
    }
}

fn main() {
    let r = Retangulo { largura: 3.0, altura: 4.0 };
    println!("{}", r.descricao());
}

Passo a passo

  1. Declaramos trait Forma com area(&self) -> f64; o ponto e vírgula indica método sem corpo, ou seja obrigatório.
  2. Dentro da trait escrevemos descricao com corpo: é um método padrão que já usa self.area().
  3. Definimos a struct Retangulo com os campos largura e altura do tipo f64.
  4. Em impl Forma for Retangulo fornecemos apenas area, multiplicando os campos.
  5. Como descricao tem corpo padrão, não precisamos reescrevê-la — Retangulo já a ganha.
  6. No main criamos o retângulo 3.0 x 4.0 e chamamos r.descricao(), que imprime a área formatada.

Por que funciona

A trait define um contrato: qualquer tipo que a implemente precisa fornecer area. O método descricao é implementado uma única vez na trait e reutilizado por todos os tipos, evitando repetição. Como descricao chama self.area(), o resultado depende da implementação específica de cada tipo, mas o código de formatação fica centralizado.

Erros comuns

  • Esquecer o &self em area: fn area() -> f64 faz o compilador reclamar que o método não pode ser chamado como self.area().
  • Tentar implementar descricao sem area: o compilador acusa que o método obrigatório area não foi implementado.
  • Usar println!("Área: {:.2}", r.area) sem parênteses: isso tenta imprimir a função, não o valor; o correto é r.area().

Outra forma de resolver

Se quiséssemos que descricao fosse diferente para cada tipo, poderíamos sobrescrevê-la no impl:

impl Forma for Retangulo {
    fn area(&self) -> f64 { self.largura * self.altura }
    fn descricao(&self) -> String { format!("Retângulo com área {:.2}", self.area()) }
}

Saída esperada

Área: 12.00