rust语言基础学习: 使用Default trait为类型提供缺省值
2020-07-21
继续学习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::TryFrom 和 std::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}