Caso de prueba: Aclaración de unidades

RustRustBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, se examina la implementación del trato Add con un parámetro de tipo fantasma utilizando el código de ejemplo proporcionado en Rust.

Nota: Si el laboratorio no especifica un nombre de archivo, puede utilizar cualquier nombre de archivo que desee. Por ejemplo, puede utilizar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/floating_types("Floating-point Types") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/DataTypesGroup -.-> rust/type_casting("Type Conversion and Casting") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/floating_types -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/string_type -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/type_casting -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/function_syntax -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/expressions_statements -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/traits -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} rust/operator_overloading -.-> lab-99356{{"Caso de prueba: Aclaración de unidades"}} end

Caso de prueba: aclaración de unidades

Un método útil de conversiones de unidades puede ser examinado implementando Add con un parámetro de tipo fantasma. El trato Add se examina a continuación:

// Esta construcción impondría: `Self + RHS = Output`
// donde RHS tiene como valor predeterminado Self si no se especifica en la implementación.
pub trait Add<RHS = Self> {
    type Output;

    fn add(self, rhs: RHS) -> Self::Output;
}

// `Output` debe ser `T<U>` para que `T<U> + T<U> = T<U>`.
impl<U> Add for T<U> {
    type Output = T<U>;
  ...
}

La implementación completa:

use std::ops::Add;
use std::marker::PhantomData;

/// Crea enumeraciones vacías para definir tipos de unidad.
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}

/// `Length` es un tipo con parámetro de tipo fantasma `Unit`,
/// y no es genérico sobre el tipo de longitud (es decir `f64`).
///
/// `f64` ya implementa los tratados `Clone` y `Copy`.
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64, PhantomData<Unit>);

/// El trato `Add` define el comportamiento del operador `+`.
impl<Unit> Add for Length<Unit> {
    type Output = Length<Unit>;

    // add() devuelve un nuevo struct `Length` que contiene la suma.
    fn add(self, rhs: Length<Unit>) -> Length<Unit> {
        // `+` llama a la implementación de `Add` para `f64`.
        Length(self.0 + rhs.0, PhantomData)
    }
}

fn main() {
    // Especifica que `one_foot` tiene el parámetro de tipo fantasma `Inch`.
    let one_foot:  Length<Inch> = Length(12.0, PhantomData);
    // `one_meter` tiene el parámetro de tipo fantasma `Mm`.
    let one_meter: Length<Mm>   = Length(1000.0, PhantomData);

    // `+` llama al método `add()` que implementamos para `Length<Unit>`.
    //
    // Dado que `Length` implementa `Copy`, `add()` no consume
    // `one_foot` y `one_meter` sino que los copia en `self` y `rhs`.
    let two_feet = one_foot + one_foot;
    let two_meters = one_meter + one_meter;

    // La adición funciona.
    println!("one foot + one_foot = {:?} in", two_feet.0);
    println!("one meter + one_meter = {:?} mm", two_meters.0);

    // Las operaciones absurdas fallan como deben:
    // Error de compilación: error de tipo de desajuste.
    //let one_feter = one_foot + one_meter;
}

Resumen

¡Felicitaciones! Has completado el laboratorio Caso de prueba: Aclaración de unidades. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.