Menu
Coddy logo textTech

複数の実装ブロック

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 ブロックの数に制限はありません。

challenge icon

チャレンジ

簡単

Player構造体を作成します。2つのフィールドは、name(String)とscore(u32)です。

構造体のメソッドを2つの独立した実装ブロックに分けて整理します。

First impl block:Constructor と query:

  • newname: Stringを受け取り、score0に設定されたPlayerを返す関連付けられた関数
  • get_score&selfを受け取り、現在のscoreをu32として返す

Second impl block:scoreの変更:

  • add_points&mut selfpoints: 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番目のラウンドのポイントを追加して最終スコアを表示する
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rustオンラインコンパイラ