FromとInto
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 57/61。
型の間で変換することは、Rustでよく行う作業です。Fromトレイトは、ある型から別の型をどのように作成できるかを定義する標準化された方法を提供します。Fromを実装すると、Intoトレイトも自動的に無料で得られます。
Fromを実装するには、別の型から自分の型を構築する方法を定義します。
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
これで、from関数またはintoメソッドを使って変換できます:
let distance = Kilometers(5.0);
// From を明示的に使用
let m1 = Meters::from(distance);
// Into を使用(From が実装されているため動作する)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
into()メソッドには型注釈が必要です。これは、Rust が変換先の型を知る必要があるためです。このパターンは、ヘルパー構造体をメインの型に変換する必要がある場合に特に便利です。たとえば、設定データを初期化済みのオブジェクトに変換したり、生の入力を検証済みの構造体に変換したりする場合です。
チャレンジ
簡単From トレイトを使って温度変換システムを構築しましょう!2つの温度型、Celsius と Fahrenheit を作成し、Rust の標準変換トレイトを使ってそれらの間の変換を実装します。
コードは2つのファイルに分けて整理します。
temperature.rs: 2つの public な newtype struct、CelsiusとFahrenheitを定義します。どちらもf64をラップします。Fromトレイトを実装し、次の formula を使ってCelsiusをFahrenheitに変換します:fahrenheit = celsius × 1.8 + 32.0。また、各 struct に inner のf64を returns するvaluemethod も追加します。main.rs: temperature module を取り込み、2つの変換方法を示します。provided input からCelsiusvalue を Create し、それをFahrenheit::from()を使ってFahrenheitに変換します。anotherCelsiusvalue を Create し、.into()method を使って変換します。両方の results を Print します。
Celsius から Fahrenheit への変換 formula は、1.8を掛けて32を加えることです。From<Celsius> for Fahrenheit を implementing すると、Celsius に Into<Fahrenheit> トレイトが automatically、free で gives されることを Remember してください!
両方の温度は whole numbers として表示されます。各 f64 を as i64 で cast します。これにより、小数部分は zero に向かって切り捨てられます。そのため、36.6 の input は 36C として Print され、変換後の 97.88 degrees Fahrenheit は 97F として Print されます。切り上げは行われません。
output には、両方の変換を次の format で表示してください。
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}Fたとえば、inputs が 0 と 100 の場合:
From: 0C = 32F
Into: 100C = 212Fまた、inputs が 25 と -40 の場合:
From: 25C = 77F
Into: -40C = -40F2つの inputs を受け取ります:1つ目の Celsius value(f64 として parse)と、2つ目の Celsius value(f64 として parse)です。
自分で試してみよう
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// 入力を読み取る
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let celsius1: f64 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let celsius2: f64 = input2.trim().parse().expect("Invalid number");
// TODO: celsius1からCelsius値を作成する
// TODO: Fahrenheit::from()を使ってFahrenheitに変換する
// TODO: celsius2から別のCelsius値を作成する
// TODO: .into()を使ってFahrenheitに変換する
// TODO: 次の形式で結果を出力する:
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ