From と Into
From トレイトと Into トレイトは本質的に結び付いており、これは実際に その実装の一部です。型 B から型 A に変換できるなら、型 B を型 A に 変換できるはずだと考えるのは自然でしょう。
From
From トレイトを使うと、ある型が別の型から自身を作成する方法を定義できます。 したがって、複数の型の間で変換するための非常に単純な仕組みを提供します。 標準ライブラリには、プリミティブ型や一般的な型の変換のために、このトレイトの実装が 数多く用意されています。
たとえば、str を String に簡単に変換できます。
#![allow(unused)] fn main() { 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 トレイトは、単に 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, } // `From` を定義 impl From<i32> for Number { fn from(item: i32) -> Self { Number { value: item } } } fn main() { let int = 5; // `Into` を使用 let num: Number = int.into(); println!("My number is {:?}", num); }