Modulelessen (1/2)
Generieken en functies
Met Generics kunt u flexibele, herbruikbare code schrijven, waarbij dubbele logica voor verschillende gegevenstypen wordt vermeden. In plaats van meerdere functies of structuren voor verschillende typen te definiëren (zoals i32, f64 of String), kunnen we een generieke typeparameter gebruiken, gewoonlijk weergegeven door de letter T.
De Rust-compiler beheert generieke codes met behulp van een proces dat monomorfisatie wordt genoemd: tijdens het compileren genereert het een kopie van de generieke code voor elk concreet type dat daadwerkelijk wordt gebruikt. Dit betekent dat er geen runtime-prestatieoverhead is.
Generieke functies
Om een generieke functie te definiëren, voegen we de typeparameter <T> direct na de functienaam en vóór de argumentenlijst in:
fn print_value<T: std::fmt::Debug>(value: T) {
println!("Value: {:?}", value);
}In generieke functies kunnen we het generieke type T gebruiken voor zowel argumenttypen als retourneringstypen:
fn identity<T>(value: T) -> T {
value
}Generieke structuren
We kunnen ook generieke typeparameters binnen structuren (struct) gebruiken om flexibele velden te definiëren:
struct KeyValuePair<K, V> {
key: K,
value: V,
}
fn main() {
let pair = KeyValuePair {
key: String::from("age"),
value: 30,
};
}In een impl blok voor een generieke structuur moeten we de typeparameter <T> onmiddellijk na het sleutelwoord impl declareren om aan te geven dat we methoden implementeren op een generieke structuur:
struct Container<T> {
value: T,
}
impl<T> Container<T> {
fn new(value: T) -> Self {
Container { value }
}
fn value(&self) -> &T {
&self.value
}
}Probeer het zelf
Oefening 1: De puntenstructuur
Definieer een generieke structuur genaamd Point<T> met twee velden: x van type T en y van type T. In de hoofdfunctie instantiëert u een variabel punt dat een punt bevat met gehele waarden x = 5 en y = 10, en drukt u vervolgens de waarde van point.x af.
Toon hint
Declareer de struct met `struct Point<T> { x: T, y: T }`. Instantieer het in main en gebruik `point.x` om het af te drukken.
Oplossing beschikbaar na 3 pogingen
Oefening 2: Een tupel omkeren met swap
Schrijf een generieke functie met de naam swap<T> die een tupel van twee elementen (T, T) accepteert en een nieuw tupel (T, T) retourneert met hun omgekeerde posities. Roep in de hoofdfunctie de functie aan met tupel (1, 2) en druk het resultaat af.
Toon hint
De functiehandtekening moet `fn swap<T>(paar: (T, T)) -> (T, T)`zijn. Retourneer de omgekeerde tupel met`(pair.1, pair.0)`.
Oplossing beschikbaar na 3 pogingen
Oefening 3: De containerstructuur
Definieer een generieke struct Container<T> die een waardeveld van het type T bevat. Implementeer een generiek impl-blok om een nieuwe methode te definiëren die een waarde van het type T accepteert en een exemplaar van Container<T> retourneert.
Toon hint
Gebruik `impl<T> Container<T>`om de bijbehorende methode `fn new(value: T) -> Self { Container { value } }` te implementeren.
Oplossing beschikbaar na 3 pogingen