前言
虽然在 Rust 中提供了用于做基本类型转换的关键字 as,但是自定义类型也有类型转换的需求,所以 Rust 标准库为我们提供了一系列 trait 来解决这个问题。本篇文章以最短的篇幅概括 类型转换相关 trait 的主要知识点。
AsRef/AsMut
这两个 trait 主要负责从 A 类型的 &self/&mut self 转换成 B 类型的 &/&mut:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
pub trait AsRef<T>
where
T: ?Sized,
{
pub fn as_ref(&self) -> &T;
}
pub trait AsMut<T>
where
T: ?Sized,
{
pub fn as_mut(&mut self) -> &mut T;
}
|
需要注意的点:
- 这两个都是用来做那种比较简单的转换,类似直接返回的那种。如果在类型转换消耗很大应该考虑使用 From 或者自定义函数
- 这两个 trait 做的类型转换都不能失败。如果类型转换存在失败的可能需要自己写自定义函数
- AsRef 和 Borrow 的区别还没真正理解,先挖个坑,等研究 HashMap 的时候再填
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
extern crate hello_rust;
struct Name(&'static str);
fn show_name<T: AsRef<Name>>(item: T) {
println!("name is :{}", item.as_ref().0);
}
struct Bus {
vehicle_name: Name,
}
impl AsRef<Name> for Bus {
fn as_ref(&self) -> &Name {
&self.vehicle_name
}
}
struct Apple {
fruit_name: Name,
}
impl AsRef<Name> for Apple {
fn as_ref(&self) -> &Name {
&self.fruit_name
}
}
fn main() {
let bus = Bus {
vehicle_name: Name("bus"),
};
let apple = Apple {
fruit_name: Name("apple"),
};
show_name(bus);
show_name(apple);
}
|
From/Into
这两个 trait 主要处理 A 和 B 值类型之间的相互转换。标准库中还存在他俩的可失败版本 TryFrom/TryInto。
1
2
3
4
5
6
7
8
|
pub trait From<T> {
#[lang = "from"]
pub fn from(T) -> Self;
}
pub trait Into<T> {
pub fn into(self) -> T;
}
|
需要注意的点:
- 因为实现 From 时标准库会有一个 Into 的预制实现。然而反过来并不是,所以我们应该优先选择实现 From trait
- 声明时优先使用 Into,因为 From 会自动实现 Into 而 Into 并不会自动实现 From
- From/Into 都不允许失败,如果有可能失败可以选择 TryFrom/TryInto
- From 在 Rust 的错误处理中应用广泛