错误特性(Error trait)

错误报告

在上一练习中,你需要解构InvalidTitle变体以提取错误信息,并将其传递给panic!宏。这是错误报告的一个(基本)示例:将错误类型转换为可以展示给用户、服务操作员或开发者的表示形式。

每个Rust开发者都提出自己的错误报告策略是不切实际的:这会浪费时间,而且在项目间组合效果也不好。这就是Rust提供std::error::Error特性的原因。

Error特性

Result中的Err变体类型没有约束,但使用实现了Error特性的类型是一个良好实践。 Error是Rust错误处理故事的基石:

#![allow(unused)]
fn main() {
// `Error`特性的简化定义
pub trait Error: Debug + Display {}
}

你可能回想起来自《Sized特性》:语法——它用于指定SuperTrait。对于Error,有两个超特性:DebugDisplay。如果一个类型想要实现Error,它也必须实现DebugDisplay

DisplayDebug

我们已经在之前的练习中遇到过Debug特性——它是assert_eq!在断言失败时显示其比较的变量值所使用的特性。

从“机械”角度看,DisplayDebug是相同的——它们编码了类型应该如何转换为字符串般的表示形式:

#![allow(unused)]
fn main() {
// `Debug`
pub trait Debug {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}

// `Display`
pub trait Display {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>;
}
}

它们的区别在于目的Display返回的表示形式是为“终端用户”准备的,而Debug提供了更适合开发者和服务操作员的低级表示。这就是为什么Debug可以通过#[derive(Debug)]属性自动实现,而Display需要手动实现。

参考

  • 本节练习位于 exercises/05_ticket_v2/09_error_trait