16.7 Boxing errors

DisplayFrom을 우리 에러 타입을 위해 구현함으로, 우리는 std 라이브러리 에러 처리 도구들을 거의 대부분 사용할 수 있었다. 하지만, 우리가 놓치고 있는 것이 있었으니: 쉽게 우리의 에러 타입을 Box하는 능력.

std 라이브러리들은 From을 통해 Error trait을 구현하는 모든 타입은 trait 객체 Box<Error>로 자동 변환된다. 라이브러리 유저에게 이는 다음과 같은 편의성을 제공한다:

fn foo(...) -> Result<T, Box<Error>> { ... }

사용자가 사용할 수 있는 다양한 외부 라이러리들은 각기 그들 자신의 고유한 에러 타입을 제공한다. 적절한 Result<T, E> 타입을 정의하기 위하여, 사용자는 몇 가지 선택지가 있다:

  • 라이브러리의 에러 타입을 포장하는 새 포장된 에러 정의
  • 에러 타입을 String이나 다른 중간 형태를 선택해 타입 변환
  • 에러 타입들을 Box하여 Box<Error>로 타입 소멸

"박싱(Boxing)"은 보편적으로 선택되는 에러 타입이다. 단점은 기본 에러 타입을 오직 런타임에만 알 수 있고 정적으로 결정되지 않는다. 위에서 언급했듯, Error trait을 구현하는 것이 필요하다:

trait Error: Debug + Display {
    fn description(&self) -> &str;
    fn cause(&self) -> Option<&Error>;
}

이 구현을 통해 가장 최근의 예제를 살펴보자. DoubleError였을 때와 마찬가지로 Box<Error>일 때도 유효하다:

use std::error;
use std::fmt;
use std::num::ParseIntError;
// `Box` .
type Result<T> = std::result::Result<T, Box<error::Error>>;
#[derive(Debug)]
enum DoubleError {
EmptyVec,
Parse(ParseIntError),
}
impl From<ParseIntError> for DoubleError {
fn from(err: ParseIntError) -> DoubleError {
DoubleError::Parse(err)
}
}
impl fmt::Display for DoubleError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
DoubleError::EmptyVec =>
write!(f, "please use a vector with at least one element"),
DoubleError::Parse(ref e) => e.fmt(f),
}
}
}
impl error::Error for DoubleError {
fn description(&self) -> &str {
match *self {
// . `Display` .
DoubleError::EmptyVec => "empty vectors not allowed",
// `Error` , .
DoubleError::Parse(ref e) => e.description(),
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
// `None` .
DoubleError::EmptyVec => None,
// `&error:Error` .
// `Error` trait .
DoubleError::Parse(ref e) => Some(e),
}
}
}
fn double_first(vec: Vec<&str>) -> Result<i32> {
let first = try!(vec.first().ok_or(DoubleError::EmptyVec));
let parsed = try!(first.parse::<i32>());
Ok(2 * parsed)
}
fn print(result: Result<i32>) {
match result {
Ok(n) => println!("The first doubled is {}", n),
Err(e) => println!("Error: {}", e),
}
}
fn main() {
let numbers = vec!["93", "18"];
let empty = vec![];
let strings = vec!["tofu", "93", "18"];
print(double_first(numbers));
print(double_first(empty));
print(double_first(strings));
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

Dynamic dispatch and Error trait

results matching ""

    No results matching ""