自定义类型转换
在 Rust 中,基本类型可以通过 casting 强制转换 相互转换。然而,自定义类型需要利用特征
(traits)来转换。通常的转换一般使用 From 和 Into 特征。
From 和 Into
From
From
特征允许类型定义如何从另一种类型创建自己。例如,你可以轻松地将 str
转换为 String
。
let a = "hello";
let b = String::from(a);
你可以为自己的类型定义转换。
use std::convert::From;
#[derive(Debug)]
struct MagicNumber {
num: i32,
}
impl From<i32> for MagicNumber {
fn from(value: i32) -> Self { // Self 在这里表示 `MagicNumber` 结构体
MagicNumber { num: value }
}
}
fn main() {
let mn = MagicNumber::from(58);
println!("{:?}", mn);
// MagicNumber { num: 58 }
}
Into
Into
特征是 From
特征的互补。
use std::convert::Into;
#[derive(Debug)]
struct MagicNumber {
num: i32,
}
impl Into<MagicNumber> for i32 {
fn into(self) -> MagicNumber { // self 在这里表示 `i32`
MagicNumber { num: self }
}
}
fn main() {
let num = 58i32;
// 此处的类型注解有助于选择使用哪个 `into` 方法
let mn: MagicNumber = num.into();
println!("{:?}", mn);
// MagicNumber { num: 58 }
}
TryFrom 和 TryInto
类似于 From
和 Into
,TryFrom
和 TryInto
也是用于在类型之间进行转换的通用特征。但它们可适用于可能失败的转换。
use std::convert::TryFrom;
struct Temperature {
value: f64,
}
impl TryFrom<f64> for Temperature {
type Error = &'static str;
fn try_from(value: f64) -> Result<Self, Self::Error> {
// 检查温度是否在有效范围内
if value < -459.67 {
Err("Temperature is below absolute zero!")
} else {
Ok(Temperature { value })
}
}
}
fn main() {
// 尝试从有效的华氏度值创建 Temperature 实例
let fahrenheit_value = 32.0;
match Temperature::try_from(fahrenheit_value) {
Ok(temp) => println!("Temperature in Celsius: {:.2}", (temp.value - 32.0) * 5.0 / 9.0),
Err(err) => println!("Error: {}", err),
}
// 摄氏度温度:0.00
// 尝试从无效的华氏度值创建 Temperature 实例
let invalid_value = -500.0;
match Temperature::try_from(invalid_value) {
Ok(temp) => println!("Temperature in Celsius: {:.2}", (temp.value - 32.0) * 5.0 / 9.0),
Err(err) => println!("Error: {}", err),
}
// 错误:温度低于绝对零度!
}
你通常不需要直接实现 TryInto
特征,而应优先实现 TryFrom
特征。因为后者提供了更大的灵活性,并且通过标准库中的通用实现加持,可以自动提供 TryInto
的等效实现。
use std::convert::TryFrom;
use std::convert::TryInto;
#[derive(Debug)]
struct Temperature {
value: f64,
}
impl TryFrom<f64> for Temperature {
type Error = &'static str;
fn try_from(value: f64) -> Result<Self, Self::Error> {
// 检查温度是否在有效范围内
if value < -459.67 {
Err("Temperature is below absolute zero!")
} else {
Ok(Temperature { value })
}
}
}
fn main() {
let result: Result<Temperature, &'static str> = 58.0_f64.try_into();
println!("{:?}", result); // Ok(Temperature { value: 58.0 })
}
字符串转换
要将任何类型转换为 String
,只需实现 ToString
特征。
不过一般情况下,都建议不要直接实现这个特征,而是实现更方便的 fmt::Display
特征。后者可自动提供 ToString
功效。
use std::fmt;
struct Temperature {
value: f64,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.2} degrees Celsius", self.value)
}
}
fn main() {
let temperature = Temperature { value: 25.0 };
println!("Current temperature: {}", temperature);
// Current temperature: 25.00 degrees Celsius
}
要将 String
转换为任何其他类型,需要实现 FromStr
特征。该特征已被标准库中许多类型实现。
pub trait FromStr: Sized {
type Err;
// 必需的方法
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
FromStr
的 from_str
方法一般被隐式使用, 被 str
的 parse
方法调用。
如果要在自定义类型上执行此操作,记得实现该特征。
fn main() {
let a: i32 = "58".parse().unwrap();
let b = "589".parse::<i32>().unwrap();
println!("Sum: {:?}", a + b); // Sum: 647
}
::<...>
是 Rust 中的所谓的 "涡轮鱼" 语法,用于显式指定转换的目标类型。
代码挑战
尝试修改编辑器中提供的代码以完成字符串解析。
Loading...
> 此处输出代码运行结果