错误特性(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
,有两个超特性:Debug
和Display
。如果一个类型想要实现Error
,它也必须实现Debug
和Display
。
Display
和Debug
我们已经在之前的练习中遇到过Debug
特性——它是assert_eq!
在断言失败时显示其比较的变量值所使用的特性。
从“机械”角度看,Display
和Debug
是相同的——它们编码了类型应该如何转换为字符串般的表示形式:
#![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