Testcase : Clarification d'unité

RustRustBeginner
Pratiquer maintenant

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

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce laboratoire, on examine l'implémentation du trait Add avec un paramètre de type fantôme à l'aide du code d'exemple fourni en Rust.

Note : Si le laboratoire ne spécifie pas de nom de fichier, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser main.rs, le compiler et l'exécuter avec 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{{"Testcase : Clarification d'unité"}} rust/floating_types -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/string_type -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/type_casting -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/function_syntax -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/expressions_statements -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/traits -.-> lab-99356{{"Testcase : Clarification d'unité"}} rust/operator_overloading -.-> lab-99356{{"Testcase : Clarification d'unité"}} end

Testcase: unit clarification

Une méthode utile de conversions d'unités peut être examinée en implémentant Add avec un paramètre de type fantôme. Le trait Add est examiné ci-dessous :

// Cette construction imposerait : `Self + RHS = Output`
// où RHS est la valeur par défaut de Self si elle n'est pas spécifiée dans l'implémentation.
pub trait Add<RHS = Self> {
    type Output;

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

// `Output` doit être `T<U>` pour que `T<U> + T<U> = T<U>`.
impl<U> Add for T<U> {
    type Output = T<U>;
  ...
}

L'implémentation complète :

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

/// Crée des énumérations vides pour définir les types d'unités.
#[derive(Debug, Clone, Copy)]
enum Inch {}
#[derive(Debug, Clone, Copy)]
enum Mm {}

/// `Length` est un type avec un paramètre de type fantôme `Unit`,
/// et n'est pas générique sur le type de longueur (c'est-à-dire `f64`).
///
/// `f64` implémente déjà les traits `Clone` et `Copy`.
#[derive(Debug, Clone, Copy)]
struct Length<Unit>(f64, PhantomData<Unit>);

/// Le trait `Add` définit le comportement de l'opérateur `+`.
impl<Unit> Add for Length<Unit> {
    type Output = Length<Unit>;

    // add() renvoie une nouvelle structure `Length` contenant la somme.
    fn add(self, rhs: Length<Unit>) -> Length<Unit> {
        // `+` appelle l'implémentation de `Add` pour `f64`.
        Length(self.0 + rhs.0, PhantomData)
    }
}

fn main() {
    // Spécifie que `one_foot` a un paramètre de type fantôme `Inch`.
    let one_foot:  Length<Inch> = Length(12.0, PhantomData);
    // `one_meter` a un paramètre de type fantôme `Mm`.
    let one_meter: Length<Mm>   = Length(1000.0, PhantomData);

    // `+` appelle la méthode `add()` que nous avons implémentée pour `Length<Unit>`.
    //
    // Étant donné que `Length` implémente `Copy`, `add()` ne consomme pas
    // `one_foot` et `one_meter` mais les copie dans `self` et `rhs`.
    let two_feet = one_foot + one_foot;
    let two_meters = one_meter + one_meter;

    // L'addition fonctionne.
    println!("one foot + one_foot = {:?} in", two_feet.0);
    println!("one meter + one_meter = {:?} mm", two_meters.0);

    // Les opérations absurdes échouent comme elles devraient :
    // Erreur de compilation : mismatch de type.
    //let one_feter = one_foot + one_meter;
}

Summary

Félicitations! Vous avez terminé le laboratoire Testcase: Unit Clarification. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.