メソッド

Rust を使用すると、関数を新しい型に関連付けることができます。これは impl ブロックで実行します。

#[derive(Debug)]
struct Race {
    name: String,
    laps: Vec<i32>,
}

impl Race {
    // レシーバなし、静的メソッド
    fn new(name: &str) -> Self {
        Self { name: String::from(name), laps: Vec::new() }
    }

    // 自身に対する排他的な読み取り / 書き込み借用アクセス
    fn add_lap(&mut self, lap: i32) {
        self.laps.push(lap);
    }

    // 自身に対する共有および読み取り専用の借用アクセス
    fn print_laps(&self) {
        println!("Recorded {} laps for {}:", self.laps.len(), self.name);
        for (idx, lap) in self.laps.iter().enumerate() {
            println!("Lap {idx}: {lap} sec");
        }
    }

    // Exclusive ownership of self (covered later)
    fn finish(self) {
        let total: i32 = self.laps.iter().sum();
        println!("Race {} is finished, total lap time: {}", self.name, total);
    }
}

fn main() {
    let mut race = Race::new("Monaco Grand Prix");
    race.add_lap(70);
    race.add_lap(68);
    race.print_laps();
    race.add_lap(71);
    race.print_laps();
    race.finish();
    // race.add_lap(42);
}

self 引数は、「レシーバ」、つまりメソッドが操作するオブジェクトを指定します。メソッドの一般的なレシーバは次のとおりです。

  • &self: 共有の不変参照を使用して、呼び出し元からオブジェクトを借用します。このオブジェクトは後で再び使用できます。
  • &mut self: 一意の可変参照を使用して、呼び出し元からオブジェクトを借用します。このオブジェクトは後で再び使用できます。
  • self: オブジェクトの所有権を取得し、呼び出し元から遠ざけます。メソッドがオブジェクトの所有者になります。所有権が明示的に送信されない限り、メソッドが戻ると、オブジェクトは破棄(デアロケート)されます。完全な所有権は、必ずしも可変性を意味するわけではありません。
  • mut self: 上記と同じですが、メソッドはオブジェクトを変更できます。
  • レシーバなし: 構造体の静的メソッドになります。通常は、new と呼ばれるコンストラクタを作成するために使用されます。
This slide should take about 8 minutes.

キーポイント:

  • メソッドを関数と比較して紹介するとよいでしょう。
    • メソッドは型(構造体や列挙型など)のインスタンスで呼び出されます。最初のパラメータはインスタンスを self として表します。
    • デベロッパーは、メソッド レシーバ構文でコードを整理する目的で、メソッドを使用することもできます。メソッドを使用することで、すべての実装コードを 1 つの予測可能な場所にまとめることができます。
  • メソッド レシーバである self というキーワードの使用について説明します。
    • self: Self の略語であることを示し、構造体名の使用方法についても説明することをおすすめします。
    • Selfimpl ブロックが存在する型の型エイリアスであり、ブロック内の他の場所で使用できることを説明します。
    • self は他の構造体と同様に使用され、ドット表記を使用して個々のフィールドを参照できることを説明します。
    • ここで finish を 2 回実行して、&selfself の違いを示すことをおすすめします。
    • self のバリアント以外にも、レシーバ型として許可されている 特別なラッパー型Box<Self> など)もあります。