Leçons du module (1/2)
Génériques et fonctions
Les generics (types génériques) permettent d'écrire du code flexible et réutilisable, en évitant la duplication de logique pour différents types de données. Au lieu de définir plusieurs fonctions ou structures pour des types différents (tels que i32, f64 ou String), nous pouvons utiliser un paramètre de type générique, conventionnellement désigné par la lettre T.
Le compilateur Rust gère les generics à l'aide d'un processus appelé monomorphisation : lors de la compilation, le compilateur génère une copie du code générique pour chaque type concret avec lequel il est réellement utilisé. De cette façon, il n'y a aucune surcharge de performance à l'exécution.
Fonctions Génériques
Pour définir une fonction générique, nous insérons le paramètre de type <T> juste après le nom de la fonction et avant la liste des paramètres :
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Valore: {:?}", value);
}
Dans les fonctions génériques, nous pouvons utiliser le type générique T à la fois pour les types des arguments et pour le type de retour :
fn identity<T>(value: T) -> T {
value
}
Structures Génériques
Nous pouvons également utiliser des paramètres de type générique à l'intérieur des structures de données (struct) pour définir des champs flexibles :
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("eta"),
value: 30,
};
}
Dans le bloc impl pour une struct générique, nous devons déclarer le paramètre de type <T> juste après le mot-clé impl pour indiquer que nous implémentons des méthodes sur une structure générique :
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}
À toi de jouer
Exercice 1 : La structure Point
Définissez une structure générique nommée Point<T> avec deux champs : x de type T et y de type T. Dans le main, instanciez une variable point contenant un Point avec des valeurs x égales à 5 et y égales à 10 (entiers), puis affichez à l'écran la valeur de point.x.
Afficher l'indice
Déclarez la struct en utilisant `struct Point<T> { x: T, y: T }`. Instanciez-la dans le main et utilisez `point.x` pour l'afficher.
Solution disponible après 3 tentatives
Exercice 2 : Inversion d'un Tuple avec swap
Écrivez une fonction générique nommée swap<T> qui accepte en entrée un tuple de deux éléments (T, T) et renvoie un nouveau tuple (T, T) avec les éléments inversés de position. Dans le main, appelez la fonction avec le tuple (1, 2) et affichez le résultat.
Afficher l'indice
La signature de la fonction doit être `fn swap<T>(pair: (T, T)) -> (T, T)`. Renvoyez le tuple inversé avec `(pair.1, pair.0)`.
Solution disponible après 3 tentatives
Exercice 3 : La structure Container
Définissez une struct générique Container<T> contenant un champ value de type T. Implémentez un bloc impl générique pour définir une méthode new qui accepte une valeur de type T et renvoie une instance de Container<T>.
Afficher l'indice
Utilisez `impl<T> Container<T>`pour implémenter la méthode associée`fn new(value: T) -> Self { Container { value } }`.
Solution disponible après 3 tentatives