Menu
Coddy logo textTech

From и Into

Часть раздела Object Oriented Programming путешествия по Rust на Coddy — урок 57 из 61.

Преобразование между типами — это распространенная задача в Rust. Трейт From предоставляет стандартизированный способ определения того, как один тип может быть создан из другого. Когда вы реализуете From, вы автоматически и бесплатно получаете трейт Into.

Для реализации From вы определяете, как создать ваш тип из другого типа:

struct Meters(f64);
struct Kilometers(f64);

impl From<Kilometers> for Meters {
    fn from(km: Kilometers) -> Self {
        Meters(km.0 * 1000.0)
    }
}

Теперь вы можете выполнить преобразование, используя либо функцию from, либо метод into:

let distance = Kilometers(5.0);

// Явное использование From
let m1 = Meters::from(distance);

// Использование Into (работает, так как реализован From)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();

Метод into() требует аннотации типа, так как Rust должен знать, в какой тип вы выполняете преобразование. Этот паттерн особенно полезен, когда у вас есть вспомогательные структуры, которые необходимо преобразовать в ваши основные типы — например, преобразование данных конфигурации в инициализированный объект или трансформация необработанных входных данных в валидированную структуру.

challenge icon

Задание

Легко

Давайте создадим систему конвертации температуры, используя трейт From! Вы создадите два типа температуры — Celsius и Fahrenheit — и реализуете преобразование между ними, используя стандартные трейты преобразования Rust.

Вы организуете свой код в двух файлах:

  • temperature.rs: Определите две публичные структуры типа newtype — Celsius и Fahrenheit — обе оборачивают f64. Реализуйте трейт From для преобразования Celsius в Fahrenheit, используя формулу: fahrenheit = celsius × 1.8 + 32.0. Также добавьте метод value в каждую структуру, который возвращает внутреннее значение f64.
  • main.rs: Подключите ваш модуль температуры и продемонстрируйте оба подхода к преобразованию. Создайте значение Celsius из предоставленных входных данных, затем преобразуйте его в Fahrenheit с помощью Fahrenheit::from(). Создайте еще одно значение Celsius и преобразуйте его с помощью метода .into(). Выведите оба результата.

Формула преобразования из Цельсия в Фаренгейт: умножить на 1.8 и прибавить 32. Помните, что реализация From<Celsius> for Fahrenheit автоматически дает вам трейт Into<Fahrenheit> для Celsius совершенно бесплатно!

Ваш вывод должен отображать оба преобразования в следующем формате:

From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}F

Например, при входных данных 0 и 100:

From: 0C = 32F
Into: 100C = 212F

И при входных данных 25 и -40:

From: 25C = 77F
Into: -40C = -40F

Вы получите два входных значения: первое значение Цельсия (парсится как f64) и второе значение Цельсия (парсится как f64).

Шпаргалка

Трейт From предоставляет стандартизированный способ преобразования между типами. Когда вы реализуете From, вы автоматически получаете реализацию трейта Into бесплатно.

Чтобы реализовать From, определите, как создать ваш тип из другого типа:

struct Meters(f64);
struct Kilometers(f64);

impl From<Kilometers> for Meters {
    fn from(km: Kilometers) -> Self {
        Meters(km.0 * 1000.0)
    }
}

Вы можете выполнять преобразование, используя либо функцию from, либо метод into:

let distance = Kilometers(5.0);

// Явное использование From
let m1 = Meters::from(distance);

// Использование Into (требуется аннотация типа)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();

Метод into() требует аннотации типа, чтобы Rust знал, в какой тип вы выполняете преобразование.

Попробуйте сами

mod temperature;

use temperature::{Celsius, Fahrenheit};

fn main() {
    // Чтение ввода
    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: Создать значение Celsius из celsius1
    // TODO: Конвертировать его в Fahrenheit, используя Fahrenheit::from()
    
    // TODO: Создать еще одно значение Celsius из celsius2
    // TODO: Конвертировать его в Fahrenheit, используя .into()
    
    // TODO: Вывести результаты в формате:
    // From: {celsius1}C = {fahrenheit1}F
    // Into: {celsius2}C = {fahrenheit2}F
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Object Oriented Programming