diff --git a/generics.md b/generics.md index 67573ba12a40c682b61dbf92a776679b0e6a58e3..6d22487d279a0a344f9a36b64f8b2e00c8720ee4 100644 --- a/generics.md +++ b/generics.md @@ -1,11 +1,151 @@ --- title: Cours de programmation séquentielle -subtitle: Génériques +subtitle: Types génériques author: Orestis Malaspinas sansfont: Sans Serif --- -# Génériques +# Types génériques -Under construction +## Généralités +- Les types génériques sont utilisés dans des fonctions, structs, enums, ... +- Permettent d'utiliser différents types concrets. +- Permettent de réduire drastiquement la quantité de code à écrire et de généraliser les concepts. + +## Exemple (1/2) + +<pre><code data-trim="hljs rust" class="lang-rust"> +fn max_i32(a: i32, b: i32) -> i32 { + if a > b { a } else { b } +} + +fn max_f64(a: f64, b: f64) -> f64 { + if a > b { a } else { b } +} + +fn main() { + let a = 1; + let b = 7; + + println!("De {} et {}, {} est le plus grand.", a, b, max_i32(a,b)); + + let a = 1.5; + let b = 7.5; + + println!("De {} et {}, {} est le plus grand.", a, b, max_f64(a,b)); +} +</code></pre> + +## Exemple (2/2) + +<pre><code data-trim="hljs rust" class="lang-rust"> +// Cette fonction ne peut pas foncitnner pour tous les types +fn max<T: PartialOrd>(a: T, b: T) -> T { + if a > b { a } else { b } // si on peut pas comparer a et b +} // cela ne peut pas compiler, d'où + // le PartialOrd +fn main() { + let a = 1; + let b = 7; + + println!("De {} et {}, {} est le plus grand.", a, b, max(a,b)); + + let a = 1.5; + let b = 7.5; + + println!("De {} et {}, {} est le plus grand.", a, b, max(a,b)); +} +</code></pre> + +# Dans les `struct` + +## Un seul type générique + +<pre><code data-trim="hljs rust" class="lang-rust"> +// Generic point +#[derive(Debug)] +struct Point<T> { + x: T, + y: T, +} + +fn main() { + let int_point = Point{ x: 1, y: 2}; // i32 point + let flt_point = Point{ x: 2.3, y: 4.7}; // f64 point + // let does_not_work_point = Point{ x: 1, y: 1.5} +} +</code></pre> + +## Deux types génériques + +<pre><code data-trim="hljs rust" class="lang-rust"> +// Generic point +#[derive(Debug)] +struct Point<T, U> { + x: T, + y: U, +} + +fn main() { + let int_point = Point{ x: 1, y: 2}; // i32 point + let flt_point = Point{ x: 2.3, y: 4.7}; // f64 point + let does_work_now_point = Point{ x: 1, y: 1.5}; // i32, f64 point +} +</code></pre> + +# Dans les méthodes + +## Exemples + +<pre><code data-trim="hljs rust" class="lang-rust"> +struct Point<T> { + x: T, + y: T, +} + +impl<T> Point<T> { + fn get_x(&self) -> &T { + &self.x + } +} + +impl Point<f64> { + fn dist(&self) -> f64 { + (self.x*self.x + self.y*self.y).sqrt() + } +} + +fn main() { + let point = Point{ x: 1, y: 2}; + println!("x = {}", point.get_x()); + let point = Point{ x: 1.0, y: 2.0}; + println!("distance = {} et x = {}", point.dist(), point.get_x()); +} +</code></pre> + +# Dans les enums + +## L'`Option<T>`{.rust} + +<pre><code data-trim="hljs rust" class="lang-rust"> +// Permet d'avoir un type générique dans Some +enum Some<T> { + Some(T), + None, +} + +fn main() { + let int_opt = Some(4); + let char_opt = Some('a'); +} +</code></pre> + +# Considérations philosophiques + +Que fait le compilateur? + +- A la compilation le type générique est remplacé par un type spécifique: monomorphisation. +- Pour chaque type, le compilateur crée une version de la fonction, struct, ... +- Et remplace la fonction générale par le code spécialisé. +- Aucun coût à l'exécution. \ No newline at end of file