From e Into
Parte da seção Programação Orientada a Objetos do Journey de Rust da Coddy. Lição 57 de 61.
Converter entre tipos é uma tarefa comum em Rust. A trait From fornece uma maneira padronizada de definir como um tipo pode ser criado a partir de outro. Quando você implementa From, obtém a trait Into automaticamente, de forma gratuita.
Para implementar From, você define como construir seu tipo a partir de outro tipo:
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
Agora você pode converter usando a função from ou o método into:
let distance = Kilometers(5.0);
// Usando From explicitamente
let m1 = Meters::from(distance);
// Usando Into (funciona porque From está implementado)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
O método into() exige uma anotação de tipo, pois o Rust precisa saber para qual tipo você está convertendo. Esse padrão é especialmente útil quando você tem estruturas auxiliares que precisam ser convertidas em seus tipos principais, como converter dados de configuração em um objeto inicializado ou transformar uma entrada bruta em uma estrutura validada.
Desafio
FácilVamos criar um sistema de conversão de temperatura usando a trait From! Você criará dois tipos de temperatura, Celsius e Fahrenheit, e implementará conversões entre eles usando as traits de conversão padrão do Rust.
Você organizará seu código em dois arquivos:
temperature.rs: Defina duas structs newtype públicas,CelsiuseFahrenheit, ambas encapsulando umf64. Implemente a traitFrompara converterCelsiusemFahrenheitusando a fórmula:fahrenheit = celsius × 1.8 + 32.0. Adicione também um métodovaluea cada struct que retorne of64interno.main.rs: Inclua seu módulo de temperatura e demonstre as duas abordagens de conversão. Crie um valorCelsiusa partir da entrada fornecida e, em seguida, converta-o paraFahrenheitusandoFahrenheit::from(). Crie outro valorCelsiuse converta-o usando o método.into(). Imprima os dois resultados.
A fórmula de conversão de Celsius para Fahrenheit é: multiplique por 1.8 e adicione 32. Lembre-se de que implementar From<Celsius> for Fahrenheit automaticamente fornece a trait Into<Fahrenheit> em Celsius gratuitamente!
As duas temperaturas são impressas como números inteiros: converta cada f64 usando as i64, o que remove as casas decimais em direção a zero. Portanto, uma entrada de 36.6 é impressa como 36C, e os 97.88 graus Fahrenheit para os quais ela é convertida são impressos como 97F. Nada é arredondado para cima.
Sua saída deve exibir as duas conversões neste formato:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}FPor exemplo, com as entradas 0 e 100:
From: 0C = 32F
Into: 100C = 212FE com as entradas 25 e -40:
From: 25C = 77F
Into: -40C = -40FVocê receberá duas entradas: o primeiro valor Celsius (analise como f64) e o segundo valor Celsius (analise como f64).
Experimente você mesmo
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// Ler 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: Crie um valor Celsius a partir de celsius1
// TODO: Converta-o para Fahrenheit usando Fahrenheit::from()
// TODO: Crie outro valor Celsius a partir de celsius2
// TODO: Converta-o para Fahrenheit usando .into()
// TODO: Imprima os resultados no formato:
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Métodos e Comportamento
Introdução a Blocos de ImplementaçãoO Parâmetro SelfMétodos MutáveisFunções AssociadasMúltiplos Blocos de ImplementaçãoEncadeamento de MétodosRecapitulação - Ações de Retângulo4Projeto: Pet Virtual
Definindo o PetAlimentando o Pet7Traits Padrão
A Trait DebugA Trait DisplayClone e CopyTraits de IgualdadeRecapitulação - Ponto Imprimível10Projeto: Sistema de Documentos
A Trait DrawComponente de Texto2Encapsulamento e Módulos
Fundamentos de MódulosA Palavra-chave PublicCampos PrivadosGettersSettersRecapitulação - Cofre Seguro5Genéricos
Structs GenéricasMétodos GenéricosMúltiplos Tipos GenéricosFunções GenéricasRecapitulação - Ponto de Coordenada8Traits como Restrições
Sintaxe de Restrições de TraitRestrições MúltiplasA Cláusula WhereRetornando Tipos com TraitsRecapitulação - Impressora Genérica11Padrões de Projeto em Rust
Padrão NewtypeComposiçãoA Trait DropFrom e IntoRecapitulação - Mock de Smart Pointer3Enums Avançados
Enums com DadosMétodos em EnumsCorrespondência de Variantes de DadosO Enum Option RevisitadoRecapitulação - Enum Shape6Definição de Traits
O que é uma Trait?Implementando TraitsImplementações PadrãoSobrescrevendo PadrõesTraits com ParâmetrosRecapitulação - Media PlayerPratique por conta própria: Compilador de Rust online