typestar

shapes.rs en Rust

Trait objects y genéricos juntos: un registro de figuras que mide y ordena.

use std::f64::consts::PI;
use std::fmt;

trait Shape {
    fn name(&self) -> &'static str;
    fn area(&self) -> f64;

    fn describe(&self) -> String {
        format!("{} of area {:.2}", self.name(), self.area())
    }
}

struct Circle {
    radius: f64,
}

struct Rect {
    width: f64,
    height: f64,
}

struct Triangle {
    base: f64,
    height: f64,
}

impl Shape for Circle {
    fn name(&self) -> &'static str {
        "circle"
    }
    fn area(&self) -> f64 {
        PI * self.radius * self.radius
    }
}

impl Shape for Rect {
    fn name(&self) -> &'static str {
        "rectangle"
    }
    fn area(&self) -> f64 {
        self.width * self.height
    }

    fn describe(&self) -> String {
        format!("{:.0}x{:.0} rectangle", self.width, self.height)
    }
}

impl Shape for Triangle {
    fn name(&self) -> &'static str {
        "triangle"
    }
    fn area(&self) -> f64 {
        self.base * self.height / 2.0
    }
}

impl fmt::Display for Circle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "circle r={}", self.radius)
    }
}

fn total_area<T: Shape>(shapes: &[T]) -> f64 {
    shapes.iter().map(|s| s.area()).sum()
}

fn main() {
    let mut shapes: Vec<Box<dyn Shape>> = vec![
        Box::new(Circle { radius: 1.5 }),
        Box::new(Rect { width: 4.0, height: 2.0 }),
        Box::new(Triangle { base: 3.0, height: 4.0 }),
    ];

    shapes.sort_by(|a, b| a.area().partial_cmp(&b.area()).unwrap());
    for s in &shapes {
        println!("{}", s.describe());
    }

    let boxes = [
        Rect { width: 1.0, height: 1.0 },
        Rect { width: 2.0, height: 3.0 },
    ];
    println!("rect total {:.1}", total_area(&boxes));
    println!("{}", Circle { radius: 2.0 });
}

Cómo funciona

  1. Un trait con un método por defecto cubre todas las figuras.
  2. Las figuras viven en un Vec<Box<dyn Shape>>, ordenadas por área.
  3. Un ayudante genérico totaliza lo que sea que implemente el trait.

Palabras clave y builtins usados aquí

El intento, en números

Líneas
86
Caracteres a escribir
1489
Tokens
496
Ritmo de tres estrellas
110 tpm

Al ritmo de tres estrellas de 110 tokens por minuto, este intento toma unos 271 segundos.

Escribe este fragmento

Paso 1 de 1 en Bis; paso 19 de 19 en Traits y genéricos.

← Anterior