From et Into
Fait partie de la section Object Oriented Programming du Journey Rust de Coddy — leçon 57 sur 61.
La conversion entre les types est une tâche courante en Rust. Le trait From fournit un moyen standardisé de définir comment un type peut être créé à partir d'un autre. Lorsque vous implémentez From, vous obtenez automatiquement le trait Into gratuitement.
Pour implémenter From, vous définissez comment construire votre type à partir d'un autre type :
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
Maintenant, vous pouvez effectuer la conversion en utilisant soit la fonction from ou la méthode into :
let distance = Kilometers(5.0);
// Utilisation explicite de From
let m1 = Meters::from(distance);
// Utilisation de Into (fonctionne car From est implémenté)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
La méthode into() nécessite une annotation de type car Rust a besoin de savoir vers quel type vous effectuez la conversion. Ce modèle est particulièrement utile lorsque vous avez des structures auxiliaires qui doivent être converties en vos types principaux — comme la conversion de données de configuration en un objet initialisé, ou la transformation d'une entrée brute en une structure validée.
Défi
FacileConstruisons un système de conversion de température en utilisant le trait From ! Vous allez créer deux types de température—Celsius et Fahrenheit—et implémenter les conversions entre eux en utilisant les traits de conversion standard de Rust.
Vous organiserez votre code sur deux fichiers :
temperature.rs: Définissez deux structs newtype publics—CelsiusetFahrenheit—enveloppant tous deux unf64. Implémentez le traitFrompour convertirCelsiusenFahrenheiten utilisant la formule :fahrenheit = celsius × 1.8 + 32.0. Ajoutez également une méthodevalueà chaque struct qui retourne lef64interne.main.rs: Importez votre module de température et démontrez les deux approches de conversion. Créez une valeurCelsiusà partir de l'entrée fournie, puis convertissez-la enFahrenheiten utilisantFahrenheit::from(). Créez une autre valeurCelsiuset convertissez-la en utilisant la méthode.into(). Affichez les deux résultats.
La formule de conversion de Celsius à Fahrenheit est : multiplier par 1.8 et ajouter 32. Rappelez-vous que l'implémentation de From<Celsius> for Fahrenheit vous donne automatiquement le trait Into<Fahrenheit> sur Celsius gratuitement !
Votre sortie doit afficher les deux conversions dans ce format :
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}FPar exemple, avec les entrées 0 et 100 :
From: 0C = 32F
Into: 100C = 212FEt avec les entrées 25 et -40 :
From: 25C = 77F
Into: -40C = -40FVous recevrez deux entrées : la première valeur Celsius (à analyser comme f64) et la seconde valeur Celsius (à analyser comme f64).
Aide-mémoire
Le trait From fournit un moyen standardisé de conversion entre les types. Lorsque vous implémentez From, vous obtenez automatiquement le trait Into gratuitement.
Pour implémenter From, définissez comment construire votre type à partir d'un autre type :
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
Vous pouvez effectuer la conversion en utilisant soit la fonction from, soit la méthode into :
let distance = Kilometers(5.0);
// Using From explicitly
let m1 = Meters::from(distance);
// Using Into (requires type annotation)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
La méthode into() nécessite une annotation de type afin que Rust sache vers quel type vous effectuez la conversion.
Essayez vous-même
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// Lire l'entrée
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let celsius1: f64 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let celsius2: f64 = input2.trim().parse().expect("Invalid number");
// TODO: Créer une valeur Celsius à partir de celsius1
// TODO: La convertir en Fahrenheit en utilisant Fahrenheit::from()
// TODO: Créer une autre valeur Celsius à partir de celsius2
// TODO: La convertir en Fahrenheit en utilisant .into()
// TODO: Afficher les résultats au format :
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Méthodes et comportement
Introduction aux blocs d'implémentationLe paramètre SelfMéthodes mutablesFonctions associéesBlocs d'implémentation multiplesChaînage de méthodesRécapitulatif - Actions sur le rectangle4Projet : Animal virtuel
Définir l'animalNourrir l'animal7Traits standards
Le trait DebugLe trait DisplayClone et CopyLes traits d'égalitéRécapitulatif - Point affichable10Projet : Système de documents
Le trait DrawComposant texte2Encapsulation et modules
Bases des modulesLe mot-clé publicChamps privésGettersSettersRécapitulatif - Casier sécurisé5Généricité
Structures génériquesMéthodes génériquesPlusieurs types génériquesFonctions génériquesRécapitulatif - Point de coordonnées8Les Traits comme contraintes
Syntaxe des contraintes de traitContraintes multiplesLa clause whereRetourner des types avec des traitsRécapitulatif - Afficheur générique11Design Patterns en Rust
Le pattern NewtypeCompositionLe trait DropFrom et IntoRécapitulatif - Mock de Smart Pointer3Enums avancées
Enums avec donnéesMéthodes sur les EnumsMatching des variantes de donnéesL'Enum Option revisitéeRécapitulatif - Enum Shape6Définition des Traits
Qu'est-ce qu'un Trait ?Implémenter des TraitsImplémentations par défautRedéfinir les comportements par défautTraits avec paramètresRécapitulatif - Lecteur multimédia