演習: 複合型を処理する
この演習では、複合データ型を使用して、自動車工場プログラムを拡張します。
タプルを使用して、関連するがデータ型が異なる 2 つの値を使用して自動車の品質を追跡します。 このタプルをこの関数の呼び出し元に返す car_quality
という名前の関数を作成します。 main
関数で、car_factory
関数を呼び出して各自動車注文を作成します。
課題は、コンパイルして実できるようにサンプル コードを完成させることです。
この演習用のサンプル コードを操作するには、次の 2 つの方法があります。
- コードをコピーし、ローカルの開発環境で編集します。
- 準備済みの Rust Playground 内でコードを開きます。
注意
サンプル コードで、todo!
マクロを探します。 このマクロは、完了または更新する必要があるコードを示しています。
タプル フィールドを持つように Car 構造体を更新する
最初のタスクは、Car
構造体の定義の変更です。 mileage
フィールドを age
という名前のタプル フィールドに移動します。 走行距離値と共に、age
タプルには、自動車が "新車" か "中古" かを識別するための別のフィールドが必要です。
サンプル コードの最初のブロックを開きます。
次のコードをコピーしてローカルの開発環境で編集するか、この用意されている Rust プレイグラウンドでコードを開きます。
#[derive(PartialEq, Debug)] // Declare Car struct to describe vehicle with four named fields struct Car { color: String, motor: Transmission, roof: bool, mileage: u32, // todo!("Move `mileage: u32` field into `age` field - a tuple with two fields: an `Age` enum, u32"); } #[derive(PartialEq, Debug)] // Declare enum for Car transmission type enum Transmission { Manual, SemiAuto, Automatic }
自動車の品質を記述するために、"新車" と "中古" の値を持つ
Age
という名前の列挙型を追加します。Car
構造体の宣言を修正します。mileage: u32
フィールドをage
という名前のタプル フィールドに置き換えます。Age
列挙値と自動車走行距離の 2 つのフィールドを持つage
タプルを定義します。
プログラムをビルドします。 次のセクションに進む前に、コードがコンパイルされることを確認してください。
コードではまだ出力は表示されませんが、エラーなしでコンパイルされる必要があります。 コンパイラからの "警告" メッセージは無視してかまいません。 警告は、列挙型と構造体の定義を宣言したものの、これらをまだ使用していないことが原因で生成されます。
car_quality 関数を作成する
次に、car_quality
という名前の新しい関数のコードを追加します。 この関数は、自動車走行距離を入力引数として受け取ります。 走行距離と自動車年数を保持するタプルを作成します。 関数から呼び出し元にタプルが返されます。
既存のコードに次のコード ブロックを追加します。 新しいコードは、ファイルの先頭または末尾に追加できます。
// Get the car quality by testing the value of the input argument // - miles (u32) // Create a tuple for the car quality with the Age ("New" or "Used") and mileage // Return a tuple with the arrow `->` syntax fn car_quality (miles: u32) -> (Age, u32) { // Declare and initialize the return tuple value // For a new car, set the miles to 0 let quality: (Age, u32) = todo!("Set the `Age` value to \"New\", set the mileage using the `miles` input argument"); // Return the completed tuple to the caller todo!("Return the tuple"); }
"新車" の
quality
タプル値を設定するコードを完成させます。関数の末尾にある
return
ステートメントを更新して、完成したタプルを呼び出し元に返します。プログラムをビルドします。 次のセクションに進む前に、コードがコンパイルされることを確認してください。 コードではまだ出力は表示されませんが、エラーなしでコンパイルされる必要があります。
car_factory 関数を更新する
次の手順では、car_factory
関数を更新します。 car_quality
関数から返されるタプルをサポートする必要があります。 Car
構造体の定義を更新したので、データを正しく処理するように関数本体を調整する必要があります。
既存のコードに次のコード ブロックを追加します。 新しいコードは、ファイルの先頭または末尾に追加できます。
// Build a new "Car" using the values of four input arguments // - color (String) // - motor (Transmission enum) // - roof (boolean, true if the car has a hard top roof) // - miles (u32) // Call the car_quality(miles) function to get the car age // Return an instance of a "Car" struct with the arrow `->` syntax fn car_factory(color: String, motor: Transmission, roof: bool, miles: u32) -> Car { // Create a new "Car" instance as requested // - Bind first three fields to values of input arguments // - "age" field calls "car_quality" function with "miles" input argument Car { color: color, motor: motor, roof: roof, mileage: miles, // todo!("Replace `mileage: miles` with `age` tuple field, call `car_quality()` with `miles` as input argument"); } }
car
変数の初期化を修正します。mileage: miles
フィールドをage
という名前のタプル フィールドに置き換えます。age
フィールドは、car_quality
関数をmiles
入力引数を使用して呼び出す必要があります。
プログラムをビルドします。 次のセクションに進む前に、コードがコンパイルされることを確認してください。
main 関数の変数を設定する
これで、main
関数の操作を開始する準備ができました。 最初の手順で、プログラムで使用する変数を定義します。
- 自動車の色の配列
- 各自動車注文の構造体
- トランスミッションの種類を記述する列挙型
main
関数の次のコード ブロックを既存のコードに追加します。 新しいコードは、ファイルの先頭または末尾に追加できます。fn main() { // Create car color array let colors = todo!("Set the enum values: 0 = Blue, 1 = Green, 2 = Red, 3 = Silver"); // Declare the car type and initial values let mut car: Car = todo!("Create `car` as a `Car` struct"); let mut engine: Transmission = todo!("Declare `engine` as a `Transmission` enum, initialize to `Manual`"); }
colors
配列変数の定義を完了します。 自動車は、青、緑、赤、シルバーの 4 色のいずれかにすることができます。car
構造体およびengine
列挙型変数の宣言構文を修正します。engine
列挙型を "Manual" に初期化します。ヒント
両方の変数を変更可能として作成することを忘れないでください。
プログラムをビルドします。 次のセクションに進む前に、コードがエラーなしでコンパイルされることを確認してください。
自動車注文を遂行する関数を呼び出す
main
関数で、自動車注文を遂行する car_factory
関数を呼び出します。 関数呼び出しでは、自動車の色が必要です。 colors
配列にインデックスを付ける方法を修正して、実際に期待された色を渡すようにする必要があります。
main
関数に次のコード ブロックを追加します。 このコードは、前の手順で追加した定義の後、かつ関数の右中かっこ}
の前に配置します。// Order 3 cars, one car for each type of transmission // Car order #1: New, Manual, Hard top car = car_factory(String::from(todo!("Index into the `colors()` array")), engine, true, 0); println!("Car order 1: {:?}, Hard top = {}, {:?}, {}, {} miles", car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #2: Used, Semi-automatic, Convertible engine = Transmission::SemiAuto; car = car_factory(String::from(todo!("Index into the `colors()` array")), engine, false, 100); println!("Car order 2: {:?}, Hard top = {}, {:?}, {}, {} miles", car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #3: Used, Automatic, Hard top engine = Transmission::Automatic; car = car_factory(String::from(todo!("Index into the `colors()` array")), engine, true, 200); println!("Car order 3: {:?}, Hard top = {}, {:?}, {}, {} miles", car.age.0, car.roof, car.motor, car.color, car.age.1);
String::from
の呼び出しでcolors
配列のインデックス付けを修正します。colors
配列には 4 つの要素があるため、注文ごとに異なる色を使用するように試行します。ヒント
配列内の要素は、インデックス位置 0 から開始します。 最初の要素の値はインデックス位置 0 にあります。
プログラムをビルドします。 コードがエラーなしでコンパイルされることを確認します。 警告メッセージはすべて無視してかまいません。
プログラムの実行
プログラムが完了すると、この例のような出力が表示されます。
Car order 1: New, Hard top = true, Manual, Blue, 0 miles
Car order 2: New, Hard top = false, SemiAuto, Green, 100 miles
Car order 3: New, Hard top = true, Automatic, Red, 200 miles
注文 2 と 3 は中古車用ですが、car_quality
関数からは現在のところ New のみが返されます。 後の演習で、条件式を使用してそれを修正し、注文を変更する方法について確認します。
解決策
この Rust Playground 内で、プログラム出力をこの演習のソリューションと比較できます。