rust로 코드를 작성하며 ?
연산자를 통해서 편리하게 에러 핸들링을 할 수 있다.
Error 타입이 달라도 컴파일 에러가 발생하지 않는 것을 보고 찾아보니 From
trait가 구현이 되어있으면 자동으로 변환이 이루어진다고 한다.
From
trait에 대해서 자세히 알아보기 위해서 작성해본다.
하나의 타입을 다른 타입으로 변환하는 기능을 제공하는 것이다.
코드로 예시를 보면
#[derive(Clone, Copy)]
struct A {
inner : i32
}
struct B {
inner : i32
}
impl From<A> for B {
fn from(value: A) -> Self {
B { inner : value.inner}
}
}
fn main() {
let a = A { inner : 10};
// 명시적 변환
let explicit_b = B::from(a);
// 암묵적 변환
let implicit_b : B = a.into();
println!("명시적으로 변환된 B : {}", explicit_b.inner);
println!("암묵적으로 변환된 B : {}", implicit_b.inner);
}
구조체 A
와 B
를 정의하고 From
trait를 B에 대해서 구현했다.
A
타입을 B로 명시적
, 암묵적
으로 변환이 가능하도록 한다.
그럼 into
는 어디서 나온 메서드인지 궁금할 수 있다.
std
의 공식문서를 보면
One should avoid implementing Into and implement From instead. Implementing From automatically provides one with an implementation of Into thanks to the blanket implementation in the standard library.
From trait를 구현하면 자동으로 into
구현이 제공된다고 나와있다.
입출력 표준 에러타입인 io
Error와 ParseIntError
가 동시에 발생할 수 있는 함수에서 CustomError
를 통해서 처리하는 방법을 코드로 알아보겠다.
use std::io;
use std::num::ParseIntError;
#[derive(Debug)]
enum CustomError {
IoError(io::Error),
ParseError(ParseIntError),
}
먼저 From
trait를 구현하지 않은 경우에 대해서 살펴본다.
fn read_and_parse(filename : &str) -> Result<i32, CustomError> {
match std::fs::read_to_string(filename) {
Ok(content) => {
match content.trim().parse() {
Ok(number) => {
Ok(number)
},
Err(e) => {
Err(CustomError::ParseError(e))
}
}
},
Err(e) => {
Err(CustomError::IoError(e))
}
}
}
두번의 match를 통해서 로직을 작성했고, Err를 반환 시 CustomError객체를 Err로 래핑하여 반환하였다.
그럼 이제 From
트레이트를 구현하여 read_and_parse
를 재작성 해보겠다.
// From trait
impl From<io::Error> for CustomError {
fn from(err : io::Error) -> Self {
CustomError::IoError(err)
}
}
impl From<ParseIntError> for CustomError {
fn from(err : ParseIntError) -> Self {
CustomError::ParseError(err)
}
}
// read_and_parse 재작성
fn read_and_parse(filename : &str) -> Result<i32, CustomError> {
let content = std::fs::read_to_string(filename)?;
let number : i32 = content.trim().parse()?;
Ok(number)
}
?
연산자를 이용하여 Result의 값이 Err이면 io::Error
와 ParseIntError
가 CustomError
로 자동 변환되어 반환되는 모습을 볼 수 있다.
코드를 간편하게 작성할 수 있게 도움을 준다.
From
trait를 구현하게 되면 자동변환으로 편리함을 제공받을 수 있다.
감사합니다.