Explorer la fonctionnalité des génériques en 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, nous allons explorer le sujet des génériques, qui consiste à généraliser les types et les fonctionnalités pour traiter une plage plus large de cas et réduire la duplication de code. La syntaxe des génériques en Rust consiste à spécifier des paramètres de type à l'aide de crochets, tels que <T>. En utilisant des génériques, nous pouvons créer des fonctions génériques qui peuvent accepter des arguments de n'importe quel type. De plus, nous pouvons définir des types génériques qui peuvent fonctionner avec différents types concrets.

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/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/integer_types("Integer Types") 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/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/integer_types -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/type_casting -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/function_syntax -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/expressions_statements -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/lifetime_specifiers -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} rust/operator_overloading -.-> lab-99344{{"Explorer la fonctionnalité des génériques en Rust"}} end

Génériques

Generics est le sujet de la généralisation des types et des fonctionnalités à des cas plus larges. Cela est extrêmement utile pour réduire la duplication de code de nombreuses manières, mais peut nécessiter une syntaxe assez complexe. Plus précisément, être générique nécessite de prendre soin de spécifier sur quels types un type générique est effectivement considéré valide. Le plus simple et le plus courant usage des génériques est pour les paramètres de type.

Un paramètre de type est spécifié comme générique en utilisant des crochets et des majuscules
typiquement représenté par <T>. En Rust, "générique" décrit également tout ce qui accepte un ou plusieurs paramètres de type générique <T>. Tout type spécifié comme paramètre de type générique est générique, et tout le reste est concret (non générique).

Par exemple, en définissant une fonction générique nommée foo qui prend un argument T de n'importe quel type :

fn foo<T>(arg: T) {... }

Comme T a été spécifié comme paramètre de type générique en utilisant <T>, il est considéré générique lorsqu'il est utilisé ici comme (arg: T). C'est le cas même si T a été précédemment défini comme un struct.

Cet exemple montre quelques éléments de syntaxe en action :

// Un type concret `A`.
struct A;

// En définissant le type `Single`, le premier usage de `A` n'est pas précédé de `<A>`.
// Par conséquent, `Single` est un type concret, et `A` est défini comme ci-dessus.
struct Single(A);
//            ^ Voici le premier usage de `Single` du type `A`.

// Ici, `<T>` précède le premier usage de `T`, donc `SingleGen` est un type générique.
// Étant donné que le paramètre de type `T` est générique, il peut être n'importe quoi, y compris
// le type concret `A` défini en haut.
struct SingleGen<T>(T);

fn main() {
    // `Single` est concret et prend explicitement `A`.
    let _s = Single(A);

    // Crée une variable `_char` de type `SingleGen<char>`
    // et lui donne la valeur `SingleGen('a')`.
    // Ici, `SingleGen` a un paramètre de type spécifié explicitement.
    let _char: SingleGen<char> = SingleGen('a');

    // `SingleGen` peut également avoir un paramètre de type spécifié implicitement :
    let _t    = SingleGen(A); // Utilise `A` défini en haut.
    let _i32  = SingleGen(6); // Utilise `i32`.
    let _char = SingleGen('a'); // Utilise `char`.
}

Sommaire

Félicitations ! Vous avez terminé le laboratoire sur les Génériques. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.