rust语言学习笔记Trait之 From 和 Into (类型转换)

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 类型"));
相关推荐
代码山河2 小时前
Python就业方向全解析:后端、爬虫、数据分析、AI你选哪个?
python·学习·架构·教程·面向对象·项目
sbjdhjd3 小时前
网工进阶笔记:H3CSE 园区网全栈技术与协议汇总
网络·笔记·云计算·ssh·网络工程·vlan·aaa
释厄6233 小时前
AI学习层更新与跨体转移律——人类社会同构·不缺理解缺 U
人工智能·学习
海绵宝宝的月光宝盒6 小时前
14-AutoCAD-阵列命令应用与案例实战(AR)
经验分享·笔记·自动化·课程设计·制造·学习方法·cad
小嘉丶学长7 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
niyongsheng7 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
白山编程大哥7 小时前
接口幂等性是什么?如何设计?
笔记
ACP广源盛139246256737 小时前
6 盘位存储扩展方案选型笔记:YLB3116 @ACP评估记录
笔记·硬件架构·硬件工程·国产芯片
小李不想当小白7 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
Hello.Reader8 小时前
tsrs 技术解析用 Rust 移植 TypeScript 7,类型检查还能怎样提速?
开发语言·rust·typescript