Contraintes de type pour les génériques Rust

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, lorsqu'on travaille avec des génériques en Rust, les paramètres de type doivent être limités par des traits pour spécifier la fonctionnalité qu'un type doit implémenter.

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/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/floating_types("Floating-point Types") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/AdvancedTopicsGroup -.-> rust/traits("Traits") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/floating_types -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/function_syntax -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/expressions_statements -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/method_syntax -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/traits -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} rust/operator_overloading -.-> lab-99348{{"Contraintes de type pour les génériques Rust"}} end

Bounds

Lorsqu'on travaille avec des génériques, les paramètres de type doivent souvent utiliser des traits comme bornes pour stipuler quelle fonctionnalité un type implémente. Par exemple, l'exemple suivant utilise le trait Display pour imprimer et donc il nécessite que T soit limité par Display ; c'est-à-dire que T doit implémenter Display.

// Définit une fonction `printer` qui prend un type générique `T` qui
// doit implémenter le trait `Display`.
fn printer<T: Display>(t: T) {
    println!("{}", t);
}

La limitation restreint le générique aux types qui respectent les bornes. C'est-à-dire :

struct S<T: Display>(T);

// Erreur! `Vec<T>` n'implémente pas `Display`. Cette
// spécialisation échouera.
let s = S(vec![1]);

Un autre effet de la limitation est que les instances génériques sont autorisées à accéder aux [méthodes] des traits spécifiés dans les bornes. Par exemple :

// Un trait qui implémente le marqueur d'impression : `{:?}`.
use std::fmt::Debug;

trait HasArea {
    fn area(&self) -> f64;
}

impl HasArea for Rectangle {
    fn area(&self) -> f64 { self.length * self.height }
}

#[derive(Debug)]
struct Rectangle { length: f64, height: f64 }
#[allow(dead_code)]
struct Triangle  { length: f64, height: f64 }

// Le générique `T` doit implémenter `Debug`. Indépendamment
// du type, cela fonctionnera correctement.
fn print_debug<T: Debug>(t: &T) {
    println!("{:?}", t);
}

// `T` doit implémenter `HasArea`. Tout type qui répond
// à la contrainte peut accéder à la fonction `area` de `HasArea`.
fn area<T: HasArea>(t: &T) -> f64 { t.area() }

fn main() {
    let rectangle = Rectangle { length: 3.0, height: 4.0 };
    let _triangle = Triangle  { length: 3.0, height: 4.0 };

    print_debug(&rectangle);
    println!("Area: {}", area(&rectangle));

    //print_debug(&_triangle);
    //println!("Area: {}", area(&_triangle));
    // ^ TODO: Essayez de décommenter cela.
    // | Erreur : Ne implémente ni `Debug` ni `HasArea`.
}

Pour information supplémentaire, les clauses where peuvent également être utilisées pour appliquer des bornes dans certains cas pour être plus expressif.

Résumé

Félicitations! Vous avez terminé le laboratoire Bounds. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.