Rust 类型转换

184 阅读3分钟

在 Rust 中,类型转换分为隐式类型转换(自动转换)和显式类型转换。

隐式类型转换(自动转换)

Rust 中的隐式类型转换非常有限,主要发生在一些安全且不会丢失信息的场景中,例如整数类型的提升。

整数类型提升

当较小的整数类型赋值给较大的整数类型时,Rust 会自动进行转换。

fn main() { 
    let num: u8 = 250; 
    let larger_num: u16 = num; // 隐式将 u8 转换为 u16 
    println!("Larger num: {}", larger_num); } 

在这个例子中,u8 类型的 num 被隐式转换为 u16 类型的 larger_num,因为 u16 能表示的范围比 u8 大,这种转换是安全的。

显式类型转换

当需要进行更复杂或可能丢失信息的类型转换时,就需要使用显式类型转换。Rust 提供了多种方式进行显式类型转换。

1. as 关键字

as 关键字是 Rust 中最常用的类型转换方式,它可以用于基本数据类型之间的转换。

fn main() { 
    let num: u16 = 257; 
    let smaller_num: u8 = num as u8; // 显式将 u16 转换为 u8 
    println!("Smaller num: {}", smaller_num); } 

这里将 u16 类型的 num 转换为 u8 类型的 smaller_num。 需要注意的是,由于 u8 的范围是 0 - 255,257 超出了这个范围,转换后会发生截断,结果为 1(257 % 256)。

2. 自定义类型转换

对于自定义类型,我们可以通过实现 FromInto 特质来实现类型转换。

From 特质

From 特质允许你定义如何从一个类型创建另一个类型。

#[derive(Debug)] 
struct Number { 
    value: i32, 
} 
impl From<i32> for Number { 
    fn from(item: i32) -> Self { 
        Number { value: item } 
    } 
} 
fn main() { 
    let num = Number::from(42); 
    println!("{:?}", num); 
} 

在这个例子中,我们为 Number 结构体实现了 From<i32> 特质,这样就可以通过 Number::from 方法从 i32 类型创建 Number 类型的实例。

Into 特质

Into 特质与 From 特质相关,一旦实现了 From 特质,Into 特质会自动实现。

#[derive(Debug)] 
struct Number { 
    value: i32, 
} 
impl From<i32> for Number { 
    fn from(item: i32) -> Self { 
        Number { value: item } 
    } 
} 

fn main() { 
    let num: i32 = 42; 
    let number: Number = num.into(); 
    println!("{:?}", number); 
} 

这里我们使用 into 方法将 i32 类型的 num 转换为 Number 类型的 number

3. TryFromTryInto 特质

当类型转换可能失败时,可以使用 TryFromTryInto 特质。

use std::convert::TryFrom; 

#[derive(Debug, PartialEq)] 
struct EvenNumber(i32); 
impl TryFrom<i32> for EvenNumber { 
    type Error = &'static str; 
    fn try_from(value: i32) -> Result<Self, Self::Error> { 
        if value % 2 == 0 { 
            Ok(EvenNumber(value)) 
        } else { 
            Err("Not an even number") 
        } 
    } 
} 

fn main() { 
    let num = 4; 
    match EvenNumber::try_from(num) { 
        Ok(even_num) => println!("{:?}", even_num), 
        Err(err) => println!("Error: {}", err), 
    } 
    
    let odd_num = 5; 
    match EvenNumber::try_from(odd_num) { 
        Ok(even_num) => println!("{:?}", even_num), 
        Err(err) => println!("Error: {}", err), 
    } 
} 

在这个例子中,我们为 EvenNumber 结构体实现了 TryFrom<i32> 特质,只有当传入的 i32 是偶数时,转换才能成功。

4. 字符串和其他类型的转换

  • 字符串转整数:可以使用 parse 方法。
fn main() { 
    let num_str = "42"; 
    let num: i32 = num_str.parse().unwrap(); 
    println!("Parsed number: {}", num); } 
  • 整数转字符串:可以使用 to_string 方法。
fn main() { 
    let num = 42; 
    let num_str = num.to_string(); 
    println!("Number as string: {}", num_str); 
} 

这些就是 Rust 中常见的类型转换方式,根据不同的场景选择合适的转换方法可以确保代码的正确性和安全性。