Struct para PolĂ­gono

Vamos criar um struct Poligono que contém alguns Pontos. Copie o código abaixo em https://play.rust-lang.org/ e preencha os métodos que faltam para fazer os testes passarem:

// TODO: remova a linha abaixo quando terminar sua implementação.
#![allow(unused_variables, dead_code)]

pub struct Ponto {
    // adicione atributos
}

impl Ponto {
    // adicione métodos
}

pub struct Poligono {
    // adicione atributos
}

impl Poligono {
    // adicione métodos
}

pub struct Circulo {
    // adicione atributos
}

impl Circulo {
    // adicione métodos
}

pub enum Forma {
    Poligono(Poligono),
    Circulo(Circulo),
}

#[cfg(test)]
mod tests {
    use super::*;

    fn arredonda_dois_digitos(x: f64) -> f64 {
        (x * 100.0).round() / 100.0
    }

    #[test]
    fn testa_magnitude_ponto() {
        let p1 = Ponto::new(12, 13);
        assert_eq!(arredonda_dois_digitos(p1.magnitude()), 17.69);
    }

    #[test]
    fn testa_distancia_ponto() {
        let p1 = Ponto::new(10, 10);
        let p2 = Ponto::new(14, 13);
        assert_eq!(arredonda_dois_digitos(p1.distancia(p2)), 5.00);
    }

    #[test]
    fn testa_somar_ponto() {
        let p1 = Ponto::new(16, 16);
        let p2 = p1 + Ponto::new(-4, 3);
        assert_eq!(p2, Ponto::new(12, 19));
    }

    #[test]
    fn testa_ponto_mais_a_esquerda_poligono() {
        let p1 = Ponto::new(12, 13);
        let p2 = Ponto::new(16, 16);

        let mut poli = Poligono::new();
        poli.adiciona_ponto(p1);
        poli.adiciona_ponto(p2);
        assert_eq!(poli.ponto_mais_a_esquerda(), Some(p1));
    }

    #[test]
    fn testa_iterador_poligono() {
        let p1 = Ponto::new(12, 13);
        let p2 = Ponto::new(16, 16);

        let mut poli = Poligono::new();
        poli.adiciona_ponto(p1);
        poli.adiciona_ponto(p2);

        let pontos = poli.iter().cloned().collect::<Vec<_>>();
        assert_eq!(pontos, vec![Point::new(12, 13), Point::new(16, 16)]);
    }

    #[test]
    fn testa_perimetros_forma() {
        let mut poli = Poligono::new();
        poli.adiciona_ponto(Ponto::new(12, 13));
        poli.adiciona_ponto(Ponto::new(17, 11));
        poli.adiciona_ponto(Ponto::new(16, 16));
        let formas = vec![
            Forma::from(poli),
            Forma::from(Circulo::new(Ponto::new(10, 20), 5)),
        ];
        let perimetros = formas
            .iter()
            .map(Forma::perimetro)
            .map(arredonda_dois_digitos)
            .collect::<Vec<_>>();
        assert_eq!(perimetros, vec![15.48, 31.42]);
    }
}

#[allow(dead_code)]
fn main() {}

Como as assinaturas dos métodos estão faltando nas declaraçÔes do problema, a parte principal do exercício é especificå-las corretamente. Não é preciso modificar os testes.

Outras partes interessante do exercĂ­cio:

  • Derive um trait Copy para algumas structs, jĂĄ que em testes os mĂ©todos Ă s vezes nĂŁo emprestam seus argumentos.
  • Descubra que o trait Add deve ser implementado para que dois objetos sejam adicionados via “+”. Note que nĂłs nĂŁo discutimos generics atĂ© o Dia 3.