前言
本文致力于用最短的篇幅覆盖标准库中Default trait
的主要知识点。
功能介绍
Default trait
可以用于定义类型的默认值。基础用法举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#[derive(Debug)]
struct TraitTest {
enable: bool,
type_id: i32,
}
impl Default for TraitTest {
fn default() -> Self {
TraitTest {
enable: true,
type_id: 1,
}
}
}
fn main() {
let td = TraitTest::default();
println!("{:?}", td);
}
|
如果我们就是想用字段类型本身的默认值,不想像上面的例子一样指定特定值的话,用上面的写法明显会有大段的冗余代码。
标准库已经为我们想到了:
1
2
3
4
5
6
7
8
9
10
|
#[derive(Default, Debug)]
struct TraitTest2 {
a: i32,
b: bool,
}
fn main() {
let td2 = TraitTest2::default();
println!("{:?}", td2);
}
|
这里需要注意的是在使用 #[derive]
的时候要确保类型的所有字段也都实现了 Default trait
。
一些基础类型在定义 Default trait
源码已经给他做实现了,所以我们可以直接用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/// default.rs 源码
macro_rules! default_impl {
($t:ty, $v:expr, $doc:tt) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for $t {
#[inline]
#[doc = $doc]
fn default() -> $t { $v }
}
}
}
default_impl! { (), (), "Returns the default value of `()`" }
default_impl! { bool, false, "Returns the default value of `false`" }
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }
default_impl! { usize, 0, "Returns the default value of `0`" }
/// ... 其他定义就省略了
|
在实践中我们经常会遇到一种情况:只想指定类型其中一个或几个字段的值。这种需求也有比较完美的解决方案:
1
2
3
4
5
6
7
8
|
fn main() {
let td3 = TraitTest {
enable: false,
..TraitTest::default()
};
println!("{:?}", td3);
}
|
你可能觉得像上面一样在 TraitTest
里面用 TraitTest::default()
有点冗余。这个标准库也已经想到了(虽然目前还没stable):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#![feature(default_free_fn)]
use std::default::default;
/// ... def code
fn main() {
let td3 = TraitTest {
enable: false,
..default()
};
println!("{:?}", td3);
}
|
总结
虽然Rust
比较复杂,但是真的用起来会发现不管是工具链还是代码书写总体来说是舒服的。尤其2019和2020年都已肉眼可见的速度变好。接下来我也会定期更一些Rust
相关的基础文章为将来撸代码做准备。