继续学习Rust标准库中常用的trait,在开始今天的学习之前,先把前面已经学过的trait做一个简单的复习:

  • std::str::FromStr 用于字符串slice str到其他类型的转换,一个名称为Point的类型实现了FromStr trait后,调用Point::from_str()就能完成从str到Point的转换,也可以使用str.parse()隐式调用的形式。
  • std::ops::Deref 用于不可变引用的解引用操作,Deref用于不可变引用的解引用操作,如*v。 实现Deref trait允许我们重载不可变引用的解引用运算符*。 实现了Deref trait的智能指针可以被当做常规引用来对待,以便于访问其智能指针背后的数据。Rust为了提高在函数或方法传参时的便利性,提供了Deref强制转换(Deref coercion)功能。
  • std::ops::DerefMut 用于可变引用的解引用操作,如*v = 1;。 实现DerefMut trait允许我们重载可变应用的解引用运算符*。 实现了DerefMut trait的智能指针可以被当做常规可变引用来对待。因为DerefMut tait继承了Deref trait,因此也具有"Deref强制转换功能"。
  • std::convert::From 如果一个类型实现了From<T>,则可以使用from实现从输入的T转换到该类型。实现From trait会自动为From<T>中的T实现Into trait。使用From trait还可以用于简化错误处理,在进行错误传播当上下游错误类型不一致时,通过实现From trait,使用?操作符自动实现下游到上游的错误转换。
  • 类似于From和Into,std::convert::TryFromstd::convert::TryInto 适用于易出错的转换场景,TryFrom, TryInto对比From和Into,多了个关联类型Error,try_from和try_into函数的返回值是Result,可以返回转换时出现的错误。

我们已经学习了FromStr, Deref, DerefMut, From, Into, TryFrom, TryInto这7个标准库中的trait,今天学习Default trait,使用Default trait可以为类型提供缺省值。

std::default::Default trait使用起来是十分简单的,先看一下它的定义:

1pub trait Default {
2    fn default() -> Self;
3}

为类型实现Default trait有两种方式:

  • 如果类型中的包含的其他类型都实现了Default trait,就可以通过derive宏#[derive(Default)]来为类型自动实现Default trait。
  • 手动实现Default trait

例1:

1#[derive(Default)] //无法编译通过 enum不能derive Default
2pub enum PayStatus {
3    Unpaid,
4    Paid,
5}

例2:

 1#[derive(Debug)]
 2pub enum PayStatus {
 3    Unpaid,
 4    Paid,
 5}
 6
 7// 为枚举PayStatus手工实现
 8impl Default for PayStatus {
 9    fn default() -> Self {
10        PayStatus::Unpaid
11    }
12}
13
14// Price的所有字段类型都实现了Default, 因此可以derive Default
15#[derive(Default, Debug)]
16pub struct Price {
17    original_price: f64,
18    discounted_price: f64,
19
20}
21
22// Order的所有字段类型都实现了Default,因此可以derive Default
23#[derive(Default, Debug)]
24pub struct Order {
25    id: i64,
26    pay_status: PayStatus,
27    price: Price,
28}

当类型实现了Default trait之后,在初始化时,可以部分初始化,其余部分使用Default::default()初始化。

例3:

1fn main() {
2   let order1 = Order::default();
3   let order2 = Order {
4       id: 100,
5       ..Order::default()
6   };
7   println!("order1 = {:?}", order1);
8   println!("order2 = {:?}", order2);
9}

参考