0Pricing
Learn Rust Coding · Leçon

Écrire du code générique en Rust

Apprenez à écrire des fonctions et des structures de données compatibles avec plusieurs types, afin d’améliorer la réutilisabilité du code sans sacrifier la sûreté des types.

Écrire du code générique en Rust est une leçon Learn Rust Coding gratuite sur CoddyKit. Ceci est la leçon 1 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Learn Rust Coding, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Learn Rust Coding comprend 3 leçons au total.

Pourquoi écrire du code générique ?

Imaginez que vous ayez besoin d'une fonction qui trouve le plus grand élément d'une liste. Et si vous en aviez besoin pour des nombres, puis pour des caractères et enfin pour des objets personnalisés ?

Sans les types génériques, vous écririez une fonction distincte pour chaque type, ce qui entraînerait beaucoup de code dupliqué. C'est là que les génériques entrent en jeu !

Présentation des génériques

Les génériques vous permettent d'écrire du code qui fonctionne avec plusieurs types, sans vous répéter. Ils permettent d'écrire des fonctions ou des structures de données flexibles et réutilisables.

Voyez-les comme un modèle qui peut être adapté à différents matériaux.

Votre première fonction générique

Pour rendre une fonction générique, nous déclarons des paramètres de type entre chevrons <> après le nom de la fonction. Un nom courant pour un paramètre de type est T (pour Type).

Cette fonction print_anything peut maintenant afficher n'importe quel type !

fn print_anything<T>(item: T) {
    println!("The item is: {}", item);
}

pub fn main() {
    print_anything(5);
    print_anything("hello");
    print_anything(true);
}

Explication des paramètres de type

Le <T> dans fn print_anything<T>(item: T) signifie que T est un emplacement réservé pour un type. Lorsque vous appelez la fonction avec un i32, T devient i32.

  • Paramètres de type : les types génériques sont généralement nommés à l'aide de lettres majuscules, comme T, U et V.
  • Flexibilité : le compilateur détermine le type concret lors de la compilation.

Ajouter un comportement&nbsp;: contraintes de traits

Parfois, votre fonction générique exige que son paramètre de type T possède des comportements précis. Par exemple, si vous voulez comparer deux valeurs de type T, T doit pouvoir être comparé.

Nous ajoutons des contraintes de traits pour préciser ces exigences. Ici, T: PartialOrd + Copy signifie que T doit implémenter les traits PartialOrd (ordre partiel pour la comparaison) et Copy.

fn largest<T: PartialOrd + Copy>(list: &[T]) -> T {
    let mut largest = list[0];
    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }
    largest
}

pub fn main() {
    let number_list = vec![34, 50, 25, 100, 65];
    println!("Largest number: {}", largest(&number_list));

    let char_list = vec!['y', 'm', 'a', 'q'];
    println!("Largest char: {}", largest(&char_list));
}

Syntaxe de plusieurs contraintes de traits

Vous pouvez exiger plusieurs traits pour un type générique en utilisant la syntaxe +, comme dans T: TraitA + TraitB.

Pour les contraintes complexes, vous pouvez également utiliser une clause where après la signature de la fonction, ce qui peut rendre la signature plus lisible :

fn some_function<T, U>(t: T, u: U) -> i32 where T: Display + Clone, U: Clone + Debug { /* ... */ }

Structures génériques

Tout comme pour les fonctions, vous pouvez définir des structures génériques sur un ou plusieurs paramètres de type. Cela permet à vos structures de données de contenir des données de n'importe quel type spécifié.

La structure Point<T> peut contenir des coordonnées de n'importe quel type T (par exemple i32 ou f64).

struct Point<T> {
    x: T,
    y: T,
}

pub fn main() {
    let integer_point = Point {
        x: 5,
        y: 10
    };
    let float_point = Point {
        x: 1.0,
        y: 4.0
    };

    println!("Int Point: ({}, {})", 
             integer_point.x, integer_point.y);
    println!("Float Point: ({}, {})", 
             float_point.x, float_point.y);
}

Implémenter des méthodes sur des structures génériques

Lorsque vous implémentez des méthodes pour une structure générique, vous devez spécifier le ou les paramètres de type génériques après impl.

Vous pouvez également ajouter des contraintes de traits aux méthodes si une méthode exige un comportement particulier de la part de ses types génériques.

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

pub fn main() {
    let p = Point {
        x: 5,
        y: 10
    };
    println!("p.x = {}", p.x());
}

Génériques et performances

L'une des forces de Rust est que les génériques constituent une abstraction à coût nul. Cela signifie que leur utilisation n'entraîne aucune pénalité de performance à l'exécution.

Rust y parvient grâce à la monomorphisation : lors de la compilation, le compilateur génère des versions spécialisées de votre code générique pour chaque type concret avec lequel il est utilisé. Ainsi, largest<i32> et largest<char> deviennent deux fonctions distinctes et optimisées.

Testez vos connaissances

Lesquelles des affirmations suivantes concernant les génériques de Rust sont VRAIES ?

Récapitulatif&nbsp;: la puissance des génériques

Dans cette leçon, vous avez appris les bases de l'écriture de code générique en Rust :

  • Ce qu'ils sont : une façon d'écrire du code flexible et réutilisable.
  • Fonctions génériques : utiliser <T> pour les paramètres de type.
  • Contraintes de traits : préciser les comportements requis avec T: Trait.
  • Structures génériques : créer des structures de données qui contiennent des types génériques.
  • Coût nul : les génériques de Rust sont compilés en code spécifique, sans pénalité à l'exécution.

Les génériques sont au cœur du Rust idiomatique et permettent de créer des abstractions puissantes et sûres du point de vue des types !

Questions Fréquemment Posées

La leçon « Écrire du code générique en Rust » est-elle gratuite ?

Oui — le texte complet de « Écrire du code générique en Rust » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Learn Rust Coding, passe à CoddyKit PRO. Le cours Learn Rust Coding comprend 3 leçons au total.

Qu'est-ce que j'apprendrai dans « Écrire du code générique en Rust » ?

Apprenez à écrire des fonctions et des structures de données compatibles avec plusieurs types, afin d’améliorer la réutilisabilité du code sans sacrifier la sûreté des types. Tu pratiques Learn Rust Coding avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Learn Rust Coding ?

Aucune expérience préalable n'est requise. Learn Rust Coding sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 3.

Combien de temps prend la leçon « Écrire du code générique en Rust » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Learn Rust Coding ?

Oui. Chaque leçon Learn Rust Coding inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Écrire du code générique en Rust
  2. Définir et implémenter des traits
  3. Utilisation avancée des traits : types associés
← Retour à Learn Rust Coding