From e Into
Fa parte della sezione Programmazione orientata agli oggetti del percorso Rust di Coddy. Lezione 57 di 61.
La conversione tra tipi è un'operazione comune in Rust. Il trait From fornisce un modo standardizzato per definire come un tipo può essere creato da un altro. Quando implementi From, ottieni automaticamente e gratuitamente il trait Into.
Per implementare From, definisci come costruire il tuo tipo a partire da un altro tipo:
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
Ora puoi convertire usando la funzione from oppure il metodo into:
let distance = Kilometers(5.0);
// Usando From esplicitamente
let m1 = Meters::from(distance);
// Usando Into (funziona perché From è implementato)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
Il metodo into() richiede un’annotazione di tipo, poiché Rust deve sapere in quale tipo stai convertendo. Questo schema è particolarmente utile quando hai strutture helper da convertire nei tuoi tipi principali, ad esempio per convertire i dati di configurazione in un oggetto inizializzato o trasformare input grezzi in una struttura convalidata.
Sfida
FacileCostruiamo un sistema di conversione della temperatura usando il trait From! Creerai due tipi di temperatura, Celsius e Fahrenheit, e implementerai le conversioni tra loro usando i trait di conversione standard di Rust.
Organizzerai il codice in due file:
temperature.rs: Definisci due struct newtype pubbliche,CelsiuseFahrenheit, che contengono entrambe unf64. Implementa il traitFromper convertireCelsiusinFahrenheitusando la formula:fahrenheit = celsius × 1.8 + 32.0. Aggiungi anche un metodovaluea ciascuna struct, che restituisca il valore interno di tipof64.main.rs: Includi il modulo delle temperature e mostra entrambi i metodi di conversione. Crea un valoreCelsiusa partire dall'input fornito, poi convertilo inFahrenheitusandoFahrenheit::from(). Crea un altro valoreCelsiuse convertilo usando il metodo.into(). Stampa entrambi i risultati.
La formula di conversione da Celsius a Fahrenheit è: moltiplica per 1.8 e aggiungi 32. Ricorda che implementare From<Celsius> for Fahrenheit ti fornisce automaticamente e gratuitamente il trait Into<Fahrenheit> per Celsius!
Entrambe le temperature vengono stampate come numeri interi: esegui il cast di ciascun f64 con as i64, che tronca i decimali verso zero. Quindi, un input di 36.6 viene stampato come 36C, e i 97.88 gradi Fahrenheit in cui viene convertito vengono stampati come 97F. Non si arrotonda mai per eccesso.
L'output dovrebbe mostrare entrambe le conversioni in questo formato:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}FPer esempio, con gli input 0 e 100:
From: 0C = 32F
Into: 100C = 212FE con gli input 25 e -40:
From: 25C = 77F
Into: -40C = -40FRiceverai due input: il primo valore in Celsius (da analizzare come f64) e il secondo valore in Celsius (da analizzare come f64).
Provalo tu
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// Leggi l'input
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: Crea un valore Celsius da celsius1
// TODO: Convertilo in Fahrenheit usando Fahrenheit::from()
// TODO: Crea un altro valore Celsius da celsius2
// TODO: Convertilo in Fahrenheit usando .into()
// TODO: Stampa i risultati nel formato:
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Metodi e comportamento
Introduzione ai blocchi implIl parametro selfMetodi mutabiliFunzioni associateBlocchi impl multipliConcatenamento di metodiRiepilogo - Azioni sul rettangolo4Progetto: animale domestico virtuale
Definire l'animaleNutrire l'animale7Trait standard
Il trait DebugIl trait DisplayClone e CopyTrait di uguaglianzaRiepilogo - Punto stampabile10Progetto: sistema di documenti
Il trait DrawComponente di testo2Incapsulamento e moduli
Nozioni di base sui moduliLa parola chiave publicCampi privatiGetterSetterRiepilogo - Armadietto sicuro5Generics
Struct genericheMetodi genericiPiù tipi genericiFunzioni genericheRipasso - Punto di coordinate8I Trait come vincoli
Sintassi dei vincoli sui traitVincoli multipliLa clausola whereRestituire tipi con i traitRiepilogo - Stampante generica11Modelli di progettazione in Rust
Pattern NewtypeComposizioneIl trait DropFrom e IntoRipasso - Mock con smart pointer3Enumerazioni avanzate
Enumerazioni con datiMetodi sulle enumerazioniCorrispondenza delle varianti con datiL'enumerazione Option ripresaRiepilogo - enumerazione Shape6Definizione dei trait
Che cos’è un trait?Implementare i traitImplementazioni predefiniteSovrascrivere le implementazioni predefiniteTrait con parametriRiepilogo - Lettore multimedialeEsercitati da solo: Compilatore Rust online