From e Into
Parte de la sección Programación Orientada a Objetos del Journey de Rust de Coddy. Lección 57 de 61.
Convertir entre tipos es una tarea común en Rust. El trait From proporciona una forma estandarizada de definir cómo se puede crear un tipo a partir de otro. Cuando implementas From, obtienes el trait Into automáticamente y de forma gratuita.
Para implementar From, defines cómo construir tu tipo a partir de otro tipo:
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
Ahora puedes convertir usando la función from o el método into:
let distance = Kilometers(5.0);
// Usando From explícitamente
let m1 = Meters::from(distance);
// Usando Into (funciona porque From está implementado)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
El método into() requiere una anotación de tipo, ya que Rust necesita saber a qué tipo estás convirtiendo. Este patrón es especialmente útil cuando tienes estructuras auxiliares que deben convertirse en tus tipos principales, como convertir datos de configuración en un objeto inicializado o transformar una entrada sin procesar en una estructura validada.
Desafío
Fácil¡Construyamos un sistema de conversión de temperaturas usando el trait From! Crearás dos tipos de temperatura, Celsius y Fahrenheit, e implementarás conversiones entre ellos usando los traits de conversión estándar de Rust.
Organizarás tu código en dos archivos:
temperature.rs: Define dos structs newtype públicas,CelsiusyFahrenheit, ambas envolviendo unf64. Implementa el traitFrompara convertirCelsiusenFahrenheitusando la fórmula:fahrenheit = celsius × 1.8 + 32.0. Añade también un métodovaluea cada struct que devuelva elf64interno.main.rs: Incluye tu módulo de temperaturas y demuestra ambos enfoques de conversión. Crea un valorCelsiusa partir de la entrada proporcionada y después conviértelo aFahrenheitusandoFahrenheit::from(). Crea otro valorCelsiusy conviértelo usando el método.into(). Imprime ambos resultados.
La fórmula de conversión de Celsius a Fahrenheit es: multiplicar por 1.8 y sumar 32. Recuerda que implementar From<Celsius> for Fahrenheit te proporciona automáticamente el trait Into<Fahrenheit> en Celsius de forma gratuita.
Ambas temperaturas se imprimen como números enteros: convierte cada f64 con as i64, lo que elimina los decimales hacia cero. Por lo tanto, una entrada de 36.6 se imprime como 36C, y los 97.88 grados Fahrenheit a los que se convierte se imprimen como 97F. No se redondea hacia arriba.
Tu salida debe mostrar ambas conversiones con este formato:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}FPor ejemplo, con las entradas 0 y 100:
From: 0C = 32F
Into: 100C = 212FY con las entradas 25 y -40:
From: 25C = 77F
Into: -40C = -40FRecibirás dos entradas: el primer valor Celsius (analízalo como f64) y el segundo valor Celsius (analízalo como f64).
Pruébalo tú mismo
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// Leer entrada
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 valor Celsius a partir de celsius1
// TODO: Conviértelo a Fahrenheit usando Fahrenheit::from()
// TODO: Crea otro valor Celsius a partir de celsius2
// TODO: Conviértelo a Fahrenheit usando .into()
// TODO: Imprime los resultados en el formato:
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Métodos y Comportamiento
Intro a Bloques de ImplementaciónEl Parámetro SelfMétodos MutablesFunciones AsociadasMúltiples Bloques de ImplementaciónEncadenamiento de MétodosResumen - Acciones de Rectángulo4Proyecto: Mascota virtual
Definir la mascotaAlimentar a la mascota7Traits estándar
El trait DebugEl trait DisplayClone y CopyTraits de igualdadResumen - Punto imprimible10Proyecto: Sistema de documentos
El Trait DrawComponente de texto2Encapsulamiento y módulos
Conceptos básicos de módulosLa palabra clave PublicCampos privadosGettersSettersRepaso - Casillero seguro5Genéricos
Estructuras genéricasMétodos genéricosMúltiples tipos genéricosFunciones genéricasResumen - Punto de coordenadas8Traits como límites
Sintaxis de límites de traitsLímites múltiplesLa cláusula whereRetornar tipos con traitsResumen: Impresora genérica11Patrones de diseño en Rust
Patrón NewtypeComposiciónEl Trait DropFrom e IntoResumen - Mock de Smart Pointer3Enums avanzados
Enums con datosMétodos en EnumsCoincidencia de variantes de datosEl Enum Option revisitadoResumen - Enum Shape6Definición de Traits
¿Qué es un Trait?Implementación de TraitsImplementaciones por defectoSobrescribir valores por defectoTraits con parámetrosResumen - Reproductor multimediaPractica por tu cuenta: Compilador de Rust online