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
とInto
は交換可能
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); }