From과 Into
From과 Into 트레이트는 본질적으로 연결되어 있으며, 이는 실제로 구현의 일부입니다. 만약 타입 B로부터 타입 A를 만들 수 있다면(From), 타입 B를 타입 A로 변환할 수 있다(Into)는 것을 쉽게 알 수 있습니다.
From
From 트레이트는 한 타입이 다른 타입으로부터 자신을 생성하는 방법을 정의할 수 있게 하여, 여러 타입 간의 변환을 위한 매우 단순한 메커니즘을 제공합니다. 표준 라이브러리에는 기본 타입 및 일반적인 타입의 변환을 위해 이 트레이트가 수없이 많이 구현되어 있습니다.
예를 들어, str을 String으로 쉽게 변환할 수 있습니다.
#![allow(unused)]
fn main() {
let my_str = "안녕";
let my_string = String::from(my_str);
}
우리는 자신의 타입에 대한 변환을 정의하기 위해 유사한 작업을 수행할 수 있습니다.
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let num = Number::from(30);
println!("제 숫자는 {:?}입니다", num);
}
Into
Into 트레이트는 단순히 From 트레이트의 반대입니다. 이는 한 타입을 다른 타입으로 변환하는 방법을 정의합니다.
into()를 호출할 때는 일반적으로 결과 타입을 지정해야 합니다. 대부분의 경우 컴파일러가 이를 결정할 수 없기 때문입니다.
use std::convert::Into;
#[derive(Debug)]
struct Number {
value: i32,
}
impl Into<Number> for i32 {
fn into(self) -> Number {
Number { value: self }
}
}
fn main() {
let int = 5;
// 타입 어노테이션을 제거해 보세요
let num: Number = int.into();
println!("제 숫자는 {:?}입니다", num);
}
From과 Into는 상호 교환 가능합니다
From과 Into는 상호 보완적으로 설계되었습니다. 두 트레이트 모두에 대해 구현을 제공할 필요는 없습니다. 만약 자신의 타입에 대해 From 트레이트를 구현했다면, Into는 필요할 때 이를 호출할 것입니다. 하지만 그 반대는 성립하지 않음에 유의하세요. 즉, 자신의 타입에 대해 Into를 구현한다고 해서 From 구현이 자동으로 제공되지는 않습니다.
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
// `From` 정의
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let int = 5;
// `Into` 사용
let num: Number = int.into();
println!("제 숫자는 {:?}입니다", num);
}