Rust-类型转换-From & Into

  1. 一、From & Into
    1. From
    2. Into
  2. 二、TryFrom & TryInto
  3. 三、ToString & FromStr
    1. ToString
    2. FromStr

一、From & Into

From

From trait 允许一种类型定义:根据另一种类型生成自己,提供了类型转换的机制。
标准库中也有规定原生类型及其他常见类型的转换功能。
str转为String

let my_str = "hello";
let my_string = String::from(my_str);

也可以让自定义类型实现转换机制:

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);
}

Into

Into trait 则是与From相反,将当前类型转换为指定类型。
如果实现了 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 int = 5;
// 试试删除类型说明
let num: Number = int.into();
println!("My number is {:?}", num);
}

二、TryFrom & TryInto

TryFrom 和 TryInto 是 类型转换的通用 trait。不同于 From/Into 的是,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() {
// TryFrom

assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));
assert_eq!(EvenNumber::try_from(5), Err(()));

// TryInto

let result: Result<EvenNumber, ()> = 8i32.try_into();
assert_eq!(result, Ok(EvenNumber(8)));
let result: Result<EvenNumber, ()> = 5i32.try_into();
assert_eq!(result, Err(()));
}

三、ToString & FromStr

ToString

要把任何类型转换成 String,只需要实现那个类型的 ToString trait。

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 { radius: 6 };
println!("{}", circle.to_string());
}

但是fmt::Display trait提供了更好的选择,在提供ToString的同时还可以用来打印类型。

FromStr

提供了将str切片转为指定对象的trait,并且提供了出错的类型选择。

use std::str::FromStr;
use std::num::ParseIntError;

#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32
}

impl FromStr for Point {
type Err = ParseIntError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
.split(',')
.collect();

let x_fromstr = coords[0].parse::<i32>()?;
let y_fromstr = coords[1].parse::<i32>()?;

Ok(Point { x: x_fromstr, y: y_fromstr })
}
}

let p = Point::from_str("(1,2)");
assert_eq!(p.unwrap(), Point{ x: 1, y: 2} )