前言
书接上文,这次我们来聊聊剩下的几种类型转换 trait。
Borrow/BorrowMut
前文的 AsRef<T>
更像是简单的 T getter 逻辑。而 Borrow<T>
个人理解更多表述的是针对 T 类型的拓展,本质上是针对相同意思的不同表述。说句人话,就是类似 String 和 str 的关系,虽然类型不同功能不同,但是他们在类型含义上都是表示“字符串”的意思,所以 String 表示的 “a” 和 str 表示的 “a” 应该是相等的。所以约定对于 Eq
,Ord
,Hash
trait 有 if x == y => x.borrow() == y.borrow()
。以 HashMap 举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
use std::borrow::Borrow;
use std:#️⃣:Hash;
pub struct HashMap<K, V> {
// fields omitted
}
impl<K, V> HashMap<K, V> {
pub fn insert(&self, key: K, value: V) -> Option<V>
where K: Hash + Eq
{
// ...
}
pub fn get<Q>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized
{
// ...
}
}
|
ToOwned
ToOwned 是 Borrow 的反向版本,功能类似 Clone, Clone 是从 &T 到 T,而 ToOwned 是从 &T 到 Borrow<T>
。
1
2
3
4
5
|
let s: &str = "a";
let ss: String = s.to_owned();
let v: &[i32] = &[1, 2];
let vv: Vec<i32> = v.to_owned();
|
ToString/FromStr
我们可以给类型实现 Display trait,因为 Rust 已经预定义了一个基于 Display 的实现:
1
2
3
4
5
6
7
8
9
10
|
impl<T: fmt::Display + ?Sized> ToString for T {
#[inline]
default fn to_string(&self) -> String {
use fmt::Write;
let mut buf = String::new();
buf.write_fmt(format_args!("{}", self))
.expect("a Display implementation returned an error unexpectedly");
buf
}
}
|
我在看基于旧版本的 Rust 的书中写的 Display 是可以自动 derive 的,而我在查阅当前版本的标准库文档中已经明确说明不能 derive:
Display is similar to Debug, but Display is for user-facing output, and so cannot be derived.
FromStr 提供从 &str 到 T 的转换:
1
2
3
4
5
|
pub trait FromStr {
type Err;
pub fn from_str(s: &str) -> Result<Self, Self::Err>;
}
|
由于可能出现失败的情况所以返回的是 Result<Self, Self::Err>
。