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 должен знать, в какой тип вы выполняете преобразование. Этот паттерн особенно полезен, когда у вас есть вспомогательные структуры, которые необходимо преобразовать в ваши основные типы — например, преобразование данных конфигурации в инициализированный объект или трансформация необработанных входных данных в валидированную структуру.
Задание
ЛегкоДавайте создадим систему конвертации температуры, используя трейт 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).
Попробуйте сами
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
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Object Oriented Programming
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media Player