From и Into
Часть раздела Объектно-ориентированное программирование путешествия по 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: Define две public структуры newtype —CelsiusиFahrenheit, каждая из которых содержитf64. Implement трейтFromдля преобразованияCelsiusвFahrenheitс использованием формулы:fahrenheit = celsius × 1.8 + 32.0. Также добавьте в каждую структуру методvalue, который returns внутреннее значениеf64.main.rs: Подключите модуль temperature и продемонстрируйте оба подхода к преобразованию. Create значениеCelsiusиз предоставленного input, затем преобразуйте его вFahrenheitс помощьюFahrenheit::from(). Create another значениеCelsiusи преобразуйте его с помощью метода.into(). Выведите оба результата.
Формула преобразования из Celsius в Fahrenheit: умножить на 1.8 и прибавить 32. Remember, что реализация From<Celsius> for Fahrenheit automatically gives вам трейт Into<Fahrenheit> для Celsius for free!
Обе температуры выводятся как целые числа: приведите каждое значение f64 с помощью as i64, что отбрасывает десятичную часть в направлении нуля. Поэтому input 36.6 выводится как 36C, а преобразованные в него 97.88 градусов Fahrenheit выводятся как 97F. Округления вверх не происходит.
Ваш вывод должен отображать оба преобразования в следующем формате:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}FНапример, для input 0 и 100:
From: 0C = 32F
Into: 100C = 212FА для input 25 и -40:
From: 25C = 77F
Into: -40C = -40FВы получите два input: первое значение Celsius (parse как f64) и второе значение Celsius (parse как 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
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Методы и поведение
Введение в блоки реализацииПараметр SelfИзменяемые методыАссоциированные функцииНесколько блоков реализацииЦепочки вызовов методовИтоги: действия с Rectangle4Проект: Виртуальный питомец
Определение питомцаКормление питомца2Инкапсуляция и модули
Основы модулейКлючевое слово PublicПриватные поляГеттерыСеттерыИтоги — Безопасный сейф5Обобщения
Обобщённые структурыОбобщённые методыНесколько обобщённых типовОбобщённые функцииПовторение — Координатная точка8Трейты как ограничения
Синтаксис ограничений трейтовМножественные ограниченияКонструкция whereВозврат типов с трейтамиИтоги — Обобщённый принтер11Паттерны проектирования в Rust
Паттерн NewtypeКомпозицияТрейт DropFrom и IntoИтоги — Мок-объект Smart Pointer3Продвинутые перечисления
Перечисления с даннымиМетоды в перечисленияхСопоставление вариантов с даннымиСнова об Option EnumИтоги — перечисление Shape6Определение трейтов
Что такое трейт?Реализация трейтовРеализации по умолчаниюПереопределение реализаций по умолчаниюТрейты с параметрамиИтоги — Media PlayerПотренируйтесь самостоятельно: Онлайн-компилятор Rust