FromとInto
FromトレイトとIntoトレイトは本質的に結びついており、そのことが実際の実装に反映されています。もし型Aが型Bからの型変換をサポートしているのであれば、型Bは型Aへの型変換ができると思うのが自然です。
From
Fromトレイトは、ある型に対し、別の型からその型を作る方法を定義できるようにするものです。そのため、複数の型の間で型変換を行うための非常にシンプルな仕組みを提供しています。標準ライブラリでは、基本データ型やよく使われる型に対して、このトレイトが多数実装されています。
例えば、strからStringへの型変換は簡単です。
#![allow(unused)]
fn main() {
let my_str = "hello";
let my_string = String::from(my_str);
}
We can do something similar for defining a conversion for our own type.
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トレイトは、単にFromトレイトの逆の働きをし、ある型を他の型に変換する方法を定義します。
into() の呼び出し時にはほとんどの場合戻り値の型をコンパイラが決定できません。そのため戻り値の型は明示的に指定する必要があります。
use std::convert::Into;
#[derive(Debug)]
struct Number {
value: i32,
}
impl Into<Number> for i32 {
fn into(self) -> Number {
Number { value: self }
}
}
fn main() {
let int = 5;
// ここの型アノテーションを消してみましょう。
let num: Number = int.into();
println!("My number is {:?}", num);
}
From and Into are interchangeable
From と Into は相補的にデザインされているので両方のトレイトを実装する必要はありません。From トレイトを実装すれば、 Into は必要なときに呼ばれます。ただし、逆は真ではない点に注意してください。 Into が実装されていても、 From が自動的に提供されるわけではありません。
use std::convert::From;
#[derive(Debug)]
struct Number {
value: i32,
}
// Define `From`
impl From<i32> for Number {
fn from(item: i32) -> Self {
Number { value: item }
}
}
fn main() {
let int = 5;
// use `Into`
let num: Number = int.into();
println!("My number is {:?}", num);
}