メソッド
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
の略語であることを示し、構造体名の使用方法についても説明することをおすすめします。Self
はimpl
ブロックが存在する型の型エイリアスであり、ブロック内の他の場所で使用できることを説明します。self
は他の構造体と同様に使用され、ドット表記を使用して個々のフィールドを参照できることを説明します。- ここで
finish
を 2 回実行して、&self
とself
の違いを示すことをおすすめします。 self
のバリアント以外にも、レシーバ型として許可されている 特別なラッパー型(Box<Self>
など)もあります。