複数の実装ブロック
CoddyのRustジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 5/61。
Rustでは、構造体のメソッドを複数のimplブロックに分けることができます。すべてを1つのブロックにまとめることもできますが、分けることでコードをより整理し、読みやすくできます。
機能を2つの実装ブロックに分割した構造体を次に示します。
struct BankAccount {
balance: f64,
}
// コンストラクタと基本的なクエリ
impl BankAccount {
fn new(initial: f64) -> BankAccount {
BankAccount { balance: initial }
}
fn balance(&self) -> f64 {
self.balance
}
}
// トランザクションメソッド
impl BankAccount {
fn deposit(&mut self, amount: f64) {
self.balance += amount;
}
fn withdraw(&mut self, amount: f64) {
self.balance -= amount;
}
}
両方のブロックはシームレスに連携します。Rustは、それらを1つのものとして扱います。どちらのブロックで定義されているかに関係なく、任意のメソッドを呼び出せます。
fn main() {
let mut account = BankAccount::new(100.0);
account.deposit(50.0);
println!("{}", account.balance()); // 150
}
このパターンは、struct が大きくなるにつれて特に便利になります。コンストラクタをまとめたり、読み取り専用のメソッドと変更を行うメソッドを分けたり、機能ごとに整理したりできます。struct が持てる impl ブロックの数に制限はありません。
チャレンジ
簡単Player構造体を作成します。2つのフィールドは、name(String)とscore(u32)です。
構造体のメソッドを2つの独立した実装ブロックに分けて整理します。
First impl block:Constructor と query:
new:name: Stringを受け取り、scoreが0に設定されたPlayerを返す関連付けられた関数get_score:&selfを受け取り、現在のscoreをu32として返す
Second impl block:scoreの変更:
add_points:&mut selfとpoints: u32を受け取り、pointsをscoreに加算するreset_score:&mut selfを受け取り、scoreを0に戻す
3つの入力を受け取ります。
- 1行目:プレイヤーの名前(String)
- 2行目:First roundで加算するpoints(u32)
- 3行目:Second roundで加算するpoints(u32)
Player::newを使用してプレイヤーを作成し、First roundのpointsを加算してscoreを出力します。その後、scoreをresetし、Second roundのpointsを加算して、最終的なscoreを出力します。
期待される出力形式:
{score_after_first_round}
{score_after_reset_and_second_round}自分で試してみよう
use std::io;
// TODO: name (String) と score (u32) フィールドを持つ Player 構造体を定義する
// TODO: 最初の impl ブロック - コンストラクタとクエリメソッド (new, get_score)
// TODO: 2番目の impl ブロック - スコア変更メソッド (add_points, reset_score)
fn main() {
let mut input = String::new();
// プレイヤー名を読み取る
io::stdin().read_line(&mut input).expect("Failed to read line");
let name = input.trim().to_string();
// 最初のラウンドのポイントを読み取る
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let first_round: u32 = input.trim().parse().expect("Invalid number");
// 2番目のラウンドのポイントを読み取る
input.clear();
io::stdin().read_line(&mut input).expect("Failed to read line");
let second_round: u32 = input.trim().parse().expect("Invalid number");
// TODO: Player::new を使ってプレイヤーを作成する
// TODO: 最初のラウンドのポイントを追加してスコアを表示する
// TODO: スコアをリセットする
// TODO: 2番目のラウンドのポイントを追加して最終スコアを表示する
}このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Rustオンラインコンパイラ