From:定义"如何从 A 转成 B"
impl From<A> for B:从类型A构造出类型B。实现它,你就定义了单向转换的源头逻辑
Into:自动获得的"转换为 B 的能力"(Into 是 From 的镜像 trait)
Into<U>是由From<U, T>自动派生 的 trait。只要你实现了From<T> for U,Rust 就会自动为你实现Into<U> for T。
1、A 到 B 的转换
rust
struct A(i32); // 自定义类型 A
struct B(i32); // 自定义类型 B
impl From<A> for B { // 为类型 B 实现由 A 到 B 的转换
fn from(a: A) -> Self {
Self(a.0 * 2) // 转换逻辑,返回 B
}
}
fn main() {
let a1 = A(3); // 类型 A
let b1 = B::from(a1); // 通过类型 B 显式调用,传入 A 类型的值
println!("{}", b1.0); // 6
let a2 = A(3); // 类型 A
let b2: B = a2.into(); // 自动推导,通过类型 A 的值调用 .into() 方法
println!("{}", b2.0); // 6
}
A 到 B 的转换,实例:
rust
#[derive(Default)]
struct Config {
host: String,
port: u16,
}
impl From<&str> for Config {
fn from(s: &str) -> Self {
Config {
host: s.to_string(),
port: 8080, // 默认端口
}
}
}
let cfg1 = Config::default(); // 空配置
let cfg2 = Config::from("localhost"); // 从字符串初始化
let cfg3: Config = "127.0.0.1".into(); // 更优雅的写法
Default:从无到有 ------ 初始化一个空值;From:从 A 到 B ------ 定义转换逻辑;Into:从 A 变成 B ------ 让转换自然发生
2、&str 与 String 的转换
(1)&str -> String
rust
let s = "hello";
let s1 = String::from(s); // 显式调用
let s2: String = s.into(); // 自动调用 From<&str> for String
// 实现了`Display`的类型转换为`String
let s3 = s.to_string();
(2)String -> &str
Ⅰ、&s :零成本,自动发生
String实现了Deref<Target = str>trait。String->&String-> (自动Deref) ->&str。- 实现
Deref时调用的as_str()
rust
let s: String = String::from("Hello");
let slice: &str = &s;
Ⅱ、.as_str() :显式调用
rust
let s: String = String::from("Hello");
let slice: &str = s.as_str();
3、Vec<T> 与[T;N] 、&[T]的转换
(1)[T;N] 、&[T]-> Vec<T>
rust
let list: [i32; 3] = [2, 8, 15]; // [T;N]
let list: &[i32] = &[2, 8, 15]; // &[T]
let v1 = Vec::from(list); // 显式调用
let v2: Vec<i32> = list.into(); // 自动调用 From<[T;N]> for Vec<T>
let v3: Vec<i32> = list.to_vec(); // 可以将数组、切片转为 Vec
(2)Vec<T> -> &[T]
Ⅰ、&Vec<T> :零成本,自动发生
Vec<T>实现了Deref<Target = [T]>trait。Vec<T>->&Vec<T>-> (自动Deref) ->&[T]。- 实现
Deref时调用的as_slice()
rust
let v = vec![2, 5, 9];
let l1: &[i32] = &v;
Ⅱ、.as_slice() :显式调用
rust
let v = vec![2, 5, 9];
let l1 = v.as_slice();
4、T: Into<String> 泛型约束
- 函数参数可以接收:
&str、String并自动转换为String - 所有实现了
Into<String>的类型都可以作为参数
rust
fn my_to_string<T: Into<String>>(str: T) -> String {
str.into()
}
let s1 = my_to_string("&str 类型");
let s2 = my_to_string(String::from("String 类型"));