基本类型可以通过显示类型转换机制(as
)来实现相互之间的转换。
Rust通过使用trait
来处理定制类型(enum
、struct
)之间的类型转换。
通用的类型转换一般使用的trait为From
和To
。
然而,对于常见的类型转换场景,有更多具体的trait
。
尤其是在处理关于字符串转换的场景。
traitFrom
和Into
是有内在联系的,这也是他们的实现细节的一部分。
如果你能够实现从类型A到类型B转换,那么应该相信我们可以实现从类型B到类型A的转换。
From
trait允许我们定义如何通过其他的类型来创建该类型的对象,因此提供了一个非常简单的机制来实现几个类型之间的相互转换。
这个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}
}
}
int main(){
let num = Number::from(30);
println!("My number is {:?}", num);
}
traitInto
是traitFrom
的一个简单的逆向函数。即,如果你为你的类型实现了traitFrom
,Into
将在需要的时候去调用它。
使用traitInto
需要指出我们需要转换成的目标类型,因为编译器在大多数时候无法推断出目标类型。然而,考虑到我们获取到的功能,这只是一个很小的妥协。
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);
}
与From
和Into
类似,TryFrom
和TryInto
是类型之间转换的通用的trait
。
与From
和Into
不同的是,TryFrom
和TryInto
被用来处理可能出现失败的转换,因而,他们返回的是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 {
Error(())
}
}
}
fn main(){
assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8)));
assert_eq!(EvenNumber::try_from(5), Error(()));
let result:Result<EvenNumber, ()> = 8i32.try_into();
assert_eq!(result, Ok(EvenNumber(8)));
let result:Result<EvenNumber, ()> = 5i32.try_into();
assert_eq!(result, Err(()));
}
为了把一个类型转为String
类型,我们只要实现traitToString
就可以了。
然而,我们并不会直接的这样做,我们应该实现traitfmt::Display
,这个trait会自动提供ToString
,而且会可以打印这个类型。
use std::fmt;
struct Circle{
radius: i32,
}
impl fmt::Display for Circle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Circle of radius {}", self.radius)
}
}
fn main(){
let circle = Circle{radius: 6};
println!("{}", circle.to_string());
}
一个最常见的类型转换是把一个字符串转换为一个数字。
实现这个功能的常用方法是使用parse
方法,并且使用rust类型类型推断或者使用turbofish
语法来指定类型。我们会在如下的示例代码中来使用这两个方法。
只要为该类型实现了FromStr
,就可以实现从字符串到指定类型的转换。
标准库中的很多类型都实现了该trait。如果要在用户定义的类型的上获得该功能,只要实现FromStr
就可以了。
fn main(){
let parsed: i32 = "5".parse().unwarp();
let turbo_parsed = "10".parse::<i32>().unwarp();
let sum = parsed + turbo_parsed;
println!("Sum: {:?}", sum);
}