Rust 使用 trait 解决类型之间的转换问题。最一般的转换会用到 From 和 into 两个 trait。
From 和 Into
From trait 允许一种类型定义 “怎么根据另一种类型生成自己”。str 转 String :
let my_str = "hello";let my_string = String::from(my_str);
Into trait 就是把 From trait 倒过来而已。也就是说,如果你为你的类型实现了 From,那么同时你也就免费获得了 Into。
使用 Into trait 通常要求指明要转换到的类型,因为编译器大多数时候不能推断它。
自定义转换规则:
use std::convert::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(30);println!("My number is {:?}", num);let int = 5;let num: Number = int.into();println!("My number is {:?}", num);}
TryFrom 和 TryInto
TryFrom 和 TryInto trait 用于易出错的转换,所以其返回值是 Result 型。
use std::convert::TryFrom;use std::convert::TryInto;#[derive(Debug, PartialEq)]struct EvenNumber(i32);impl TryFrom<i32> for EvenNumber {type Error = ();fn try_from(value: i32) -> Result<Self, Self::Error> {if value % 2 == 0 {Ok(EvenNumber(value))} else {Err(())}}}fn main() {// TryFromassert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));assert_eq!(EvenNumber::try_from(5), Err(()));// TryIntoassert_eq!(8.try_into(), Ok(EvenNumber(8)));let result: Result<EvenNumber, ()> = 5i32.try_into();assert_eq!(result, Err(()));}
ToString 和 FromStr
把任何类型转化成 String ,只需要实现那个类型的 ToString trait。但是建议实现 fmt::Display trait,它会自动提供 ToString ,并且还可以用来打印类型。
use std::string::ToString;struct Circle {radius: i32}impl ToString for Circle {fn to_string(&self) -> String {format!("Circle of radius {:?}", self.radius)}}fn main() {let circle = Circle {: 6 };println!("{}", circle.to_string());}
解析字符串
字符串转数字,标准手段是使用 parse 函数。需要提供转换到的类型,或者使用 turbo fish 语法实现。
只要对目标类型实现了FromStrtrait,就可以用 parse 把字符串转为目标类型。
fn main() {let parsed: i32 = "5".parse().unwrap();let turbo_parsed = "10".parse::<i32>().unwrap();let sum = parsed + turbo_parsed;println!{"Sum: {:?}", sum};}
自定义实现:
fn main() {use std::str::FromStr;#[derive(Debug)]struct Point {x: i32,y: i32,}impl FromStr for Point {type Err = ();fn from_str(s: &str) -> Result<Self, Self::Err> {let x_fromstr = s.parse::<i32>().unwrap();Ok(Point {x: x_fromstr,y: x_fromstr,})}}let p: Point = "1".parse().unwrap();// 或者使用 from_str// let p = Point::from_str("1");println!("{:?}", p);}
