「这是我参与11月更文挑战的第 19 天,活动详情查看:2021最后一次更文挑战」
From::from()关注的是目标类型,Into::into()关注的是原始值;但两者表达的是同样的转换。以上所有的转换都是等价的,选择其中一个是品味的问题。
就个人而言,我更喜欢使用 TargetType::from(value) 和 value.into()。前者使我们的意图更明确,而后者比 Into::into(value) 更短。请注意,如果我们选择 TargetType::from()以外的任何形式,我们可能需要添加类型注解来区分预期的目标类型,因为它清楚地表明了目标类型。
为U实现From的一个好处是,它意味着为T实现Into,这意味着我们免费得到一个自动的Into实现(反之则不然)。
// From implies Into
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, U> Into<U> for T where U: From<T> {
fn into(self) -> U {
U::from(self)
}
}
拥有Into实现的第二个好处(不管是显式的还是自动的)是:我们可以用它将函数参数从特定的类型拓宽到任何类型都可以转换为目标类型,如下例所示:
// 特定类型才能传入
fn do_something(value: TargetType<T>) {
// ...
}
// 扩展传入类型参数
fn do_something<U: Into<TargetType<T>>>(value: U) {
let converted_value = value.into();
// ...
}
好了,理论够了。几个例子将使我们更容易理解这一切在实践中是如何运作的。
Example: SortedVec<T>
假设我们有一个排序的Vec类型:SortedVec<T>。由于它是一个通用的数据结构,从类似切片和列表的类型中构建一个SortedVec是有常用的,下面将实现这些转换。
/// Our simple sorted vector structure is just a wrapper around a Vec
struct SortedVec<T>(Vec<T>);
/// slice -> SortedVec
impl<'a, T: Ord + Clone> From<&'a [T]> for SortedVec<T> {
fn from(slice: &[T]) -> Self {
let mut vec = slice.to_owned();
vec.sort();
SortedVec(vec)
}
}
/// 对vec进行排序,然后将其放到内部的 SortedVec
impl<T: Ord + Clone> From<Vec<T>> for SortedVec<T> {
fn from(mut vec: Vec<T>) -> Self {
vec.sort();
SortedVec(vec)
}
}
impl<T: Ord + Clone> From<LinkedList<T>> for SortedVec<T> {
fn from(list: LinkedList<T>) -> Self {
let mut vec: Vec<T> = list.iter().cloned().collect();
vec.sort();
SortedVec(vec)
}
}
现在,你可能会反对说,从Vec转换是多余的,因为我们可以从Vec中得到一个slice,然后再转换这个slice。这是完全正确的,然而,上面的实现避免了克隆向量,而且,在我看来,隐藏任何中间步骤会带来一个更令人愉快的API。
作为上述特质实现的结果,我们可以调用 SortedVec::from(),而不必关心参数是否是 slice、Vector 或 LinkedList。
let vec = vec![1u8, 2, 3];
// Convert a slice
let sorted = SortedVec::from(&vec[1..]);
// ... a vector
let sorted = SortedVec::from(vec);
// ... a linked list
let mut linked_list: LinkedList<u8> = LinkedList::new();
linked_list.extend(&[1, 2, 3]);
let sorted = SortedVec::from(linked_list);