Если вы новичок в Rust, то трейты
From
и Into
могут показаться вам запутанными, но это интересные системы характеристик Rust. В этой статье мы будем изучать трейты характеристик на примерах.
Характеристики From
и Into
по своей сути связаны, и на самом деле это части реализации трейта. Если вы можете преобразовать тип A
из типа B
, то должно быть так же легко преобразовать тип B
в тип A
.
Трейт From
Трейт From предоставляет возможность создать характеристику преобразования, он позволяет вам преобразовывать значения одного типа в значения другого типа. Например, стандартная библиотека реализует impl From<&'_ str> for String
, который позволяет вам генерировать строку из &str
.
Например, мы можем легко преобразовать срез &str
в строку:
let my_str = "Привет всем";
let my_string = String::from(my_str);
Другой пример характеристики:
Предположим, мы хотим реализовать нашу собственную характеристику From<String> for SplitName
. Это позволило бы нам разделить любое заданное имя, разделенное пробелом, на структуру, содержащую имя и фамилию. Это можно легко сделать, используя трейт From
. Ниже приведен пример того же самого.
use std::convert::From;
#[derive(Debug)]
struct SplitName{
first_name: String,
last_name: String,
}
impl From<String> for SplitName {
fn from(item: String) -> Self {
let name_vector:Vec<&str> = item.split_whitespace().collect();
SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string(), }
}
}
fn main() {
let from_example = SplitName::from("Имя Фамилия".to_string());
println!("Имя: {:?}", from_example);
}
Имя: SplitName { first_name: "Имя", last_name: "Фамилия" }
Параметр From
также очень полезен при выполнении обработки ошибок. При построении функции, способной к сбою, возвращаемый тип обычно будет иметь вид Result<T, E>
.
Примечание: Этот трейт не должен подводить. Характеристика From предназначена для идеальных конверсий. Если преобразование может завершиться неудачей или не является совершенным, используйте TryFrom.
Трейт Into
Трейт Into
противоположен трейту From
. Реализация From
автоматически обеспечивает реализацию трейта Into
. Следует избегать реализации Into
и вместо этого внедрять From
.
Использование характеристики Into обычно требует спецификации типа для преобразования, поскольку компилятор не может определить это большую часть времени.
Например, мы можем легко преобразовать &str
в строку:
let my_str = "Привет всем";
let my_string: String = my_str.into();
Снова используя приведенный выше пример, чтобы разделить любое заданное имя, разделенное пробелом, на структуру, содержащую имя и фамилию, мы можем разделить имя напрямую, вызвав .into()
для заданного имени после преобразования его в строку. Здесь мы должны предоставить спецификацию следующим образом: let into_example: SplitName = "Привет всем".to_string().into();
Вот полный код для преобразования имени в SplitName
с использованием характеристик From и Into:
use std::convert::From;
#[derive(Debug)]
struct SplitName{
first_name: String,
last_name: String,
}
impl From<String> for SplitName {
fn from(item: String) -> Self {
let name_vector:Vec<&str> = item.split_whitespace().collect();
SplitName { first_name : name_vector[0].to_string(), last_name :name_vector[1].to_string(), }
}
}
fn main() {
let from_example = SplitName::from("Имя Фамилия".to_string());
println!("Имя использует from: {:?}", from_example);
let into_example :SplitName = "Int Main".to_string().into();
println!("Имя использует into: {:?}", into_example);
}
Имя использует from: SplitName { first_name: "Имя", last_name: "Фамилия" }
Имя использует into: SplitName { first_name: "Имя", last_name: "Фамилия" }
Вы вольны использовать into() и from(), и вам решать, какой из них наиболее выразителен для вашего кода, но предпочитает использовать Into вместо From при указании характеристики для универсальной функции, чтобы гарантировать, что типы, которые реализуют только Into, также могут быть использованы.
Примечание: Этот трейт не должен подводить. Если преобразование может завершиться неудачей, используйте TryInto.
Вывод
Трейты From
и Into
в Rust используются для выполнения преобразований типов. Трейт From
позволяет вам преобразовывать значения одного типа в значения другого типа, реализуя метод from
. Трейт Into
является упрощенной версией трейта From
и позволяет осуществлять более простое преобразование путем реализации метода into
.
Основное различие между ними заключается в том, что трейт Into
предполагает, что преобразование всегда будет успешным, в то время как трейт “From” допускает возможность неудачного преобразования, что достигается путем возврата типа результата из реализации метода from, который может быть либо в порядке с преобразованным значением, или ошибка с описанием ошибки.