FromとInto
CoddyのRustジャーニー「Object Oriented Programming」セクションの一部 — レッスン 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 トレイトを使用して、温度変換システムを構築しましょう!Celsius(摂氏)と Fahrenheit(華氏)という2つの温度型を作成し、Rustの標準的な変換トレイトを使用してそれらの間の変換を実装します。
コードは2つのファイルに分けて構成します:
temperature.rs:f64をラップする2つのパブリックなニュータイプ構造体CelsiusとFahrenheitを定義します。fahrenheit = celsius × 1.8 + 32.0という公式を使用して、CelsiusをFahrenheitに変換するためのFromトレイトを実装してください。また、各構造体に内部のf64を返すvalueメソッドを追加してください。main.rs: 作成した温度モジュールを取り込み、両方の変換方法を実演します。提供された入力からCelsiusの値を作成し、Fahrenheit::from()を使用してFahrenheitに変換します。もう一つのCelsiusの値を作成し、.into()メソッドを使用して変換します。両方の結果を出力してください。
摂氏から華氏への変換公式は、1.8を掛けて32を足すことです。From<Celsius> for Fahrenheit を実装すると、Celsius に対して Into<Fahrenheit> トレイトが自動的に提供されることを忘れないでください!
出力は、以下の形式で両方の変換を表示する必要があります:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}F例えば、入力が 0 と 100 の場合:
From: 0C = 32F
Into: 100C = 212F入力が 25 と -40 の場合:
From: 25C = 77F
Into: -40C = -40F2つの入力を受け取ります:1つ目の摂氏の値(f64 としてパース)と、2つ目の摂氏の値(f64 としてパース)です。
チートシート
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を使用する(型注釈が必要)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
into()メソッドは、Rustがどの型に変換しようとしているかを認識できるように、型注釈を必要とします。
自分で試してみよう
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
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。