From e Into
Parte de la sección Object Oriented Programming 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 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 realizar la conversión utilizando ya sea 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 necesitan ser convertidas a tus tipos principales—como convertir datos de configuración en un objeto inicializado, o transformar una entrada bruta en una estructura validada.
Desafío
Fácil¡Vamos a construir un sistema de conversión de temperatura utilizando el trait From! Crearás dos tipos de temperatura—Celsius y Fahrenheit—e implementarás conversiones entre ellos utilizando los traits de conversión estándar de Rust.
Organizarás tu código en dos archivos:
temperature.rs: Define dos structs newtype públicos—CelsiusyFahrenheit—ambos envolviendo unf64. Implementa el traitFrompara convertirCelsiusenFahrenheitusando la fórmula:fahrenheit = celsius × 1.8 + 32.0. También añade un métodovaluea cada struct que devuelva elf64interno.main.rs: Incorpora tu módulo de temperatura y demuestra ambos enfoques de conversión. Crea un valorCelsiusa partir de la entrada proporcionada, luego 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 otorga automáticamente el trait Into<Fahrenheit> en Celsius de forma gratuita!
Tu salida debe mostrar ambas conversiones en 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 (analizado como f64) y el segundo valor Celsius (analizado como f64).
Pruébalo tú mismo
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// Leer la 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: Crear un valor Celsius a partir de celsius1
// TODO: Convertirlo a Fahrenheit usando Fahrenheit::from()
// TODO: Crear otro valor Celsius a partir de celsius2
// TODO: Convertirlo a Fahrenheit usando .into()
// TODO: Imprimir 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 Object Oriented Programming
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 multimedia