概要
メソッドは、よく使用する処理を手軽に実行することができるものである。
メソッドを呼び出すには、数値や文字列などの任意の引数を用意して実行する。
そして、実行した結果を戻り値として返す。
このメソッドの結果を、他の処理や演算に利用することもできる。
Rustには、標準ライブラリに多くのメソッドが用意されている。
Rustの標準ライブラリは、Rustの公式Webサイト で確認することができる。
メソッド
メソッドの定義
メソッドを作成するには関数名が必要である。
Rustのメソッド名は、スネークケースで記述するのが慣習である。
- 小文字の英字 (a-z)
- 数字 (0-9)
※ただし、関数の先頭文字としては使用できない。 - アンダースコア (_)
関数の作成
関数を定義するには、fn キーワードを使用する。
fnに続けて関数名を記述した後、丸括弧()を記述する。
丸括弧()の中には引数の定義を入れる場合もある。
戻り値の型がある場合は、-> に続けて型を指定する。
関数本体は波括弧 {} で囲む。
fn 関数名([引数名: 型, ...]) [-> 戻り値の型] {
実行コード
}
以下の例では、Hello!と出力するsay_hello関数である。
fn say_hello() {
println!("Hello!");
}
fn main() {
say_hello();
}
// 出力
Hello!
上記のsay_hello関数を変更して、引数に名前を入れてHello! <名前>を出力するメソッドを定義する。
fn say_hello(name: &str) {
println!("Hello! {}", name);
}
fn main() {
say_hello("Rust");
}
// 出力
Hello! Rust
標準ライブラリの関数の使用
標準ライブラリの関数を使用するには、関数名に丸括弧 () を付けて呼び出す。
fn main() {
let s = "Rust";
println!("{}", s.len());
}
// 出力
4
※注意
Rustでは、全ての関数の引数と戻り値の型を明示的に指定する必要がある。
メソッド名は、スネークケースで記述するのが慣習である。
引数
位置引数
メソッドの引数は複数指定できる。
引数は位置によって対応付けられ、呼び出し時に順番通りに渡される。
全ての引数には型を明示的に指定する必要がある。
fn dinner_menu(food: &str, drink: &str, dessert: &str) {
println!("夕食は{}を用意しています。", food);
println!("飲み物は{}をおすすめします。", drink);
println!("デザートに{}をどうぞ。", dessert);
}
fn main() {
dinner_menu("定食", "お茶", "ゼリー");
}
// 出力
夕食は定食を用意しています。
飲み物はお茶をおすすめします。
デザートにゼリーをどうぞ。
※注意
Rustには、キーワード引数の機能はない。
引数は常に位置によって対応付けられる。
デフォルト引数
Rustには、デフォルト引数の機能は存在しない。
しかし、Option型やメソッドのオーバーロードの代替として、複数のメソッドを定義することで同様の効果を得ることができる。
以下の例では、Option型を使用してデフォルト値を実現している。
fn dinner_menu(food: Option<&str>, drink: Option<&str>, dessert: Option<&str>) {
let food = food.unwrap_or("定食");
let drink = drink.unwrap_or("お茶");
let dessert = dessert.unwrap_or("ゼリー");
println!("夕食は{}を用意しています。", food);
println!("飲み物は{}をおすすめします。", drink);
println!("デザートに{}をどうぞ。", dessert);
}
fn main() {
// 全てデフォルト値を使用
dinner_menu(None, None, None);
// 一部を指定
dinner_menu(Some("ハンバーグ"), Some("赤ワイン"), Some("シャーベット"));
}
// 出力
夕食は定食を用意しています。
飲み物はお茶をおすすめします。
デザートにゼリーをどうぞ。
夕食はハンバーグを用意しています。
飲み物は赤ワインをおすすめします。
デザートにシャーベットをどうぞ。
あるいは、ビルダーパターンを使用する方法もある。
struct DinnerMenu {
food: String,
drink: String,
dessert: String,
}
impl DinnerMenu {
fn new() -> Self {
DinnerMenu {
food: "定食".to_string(),
drink: "お茶".to_string(),
dessert: "ゼリー".to_string(),
}
}
fn food(mut self, food: &str) -> Self {
self.food = food.to_string();
self
}
fn drink(mut self, drink: &str) -> Self {
self.drink = drink.to_string();
self
}
fn dessert(mut self, dessert: &str) -> Self {
self.dessert = dessert.to_string();
self
}
fn show(&self) {
println!("夕食は{}を用意しています。", self.food);
println!("飲み物は{}をおすすめします。", self.drink);
println!("デザートに{}をどうぞ。", self.dessert);
}
}
fn main() {
// デフォルト値を使用
DinnerMenu::new().show();
// 一部を変更
DinnerMenu::new()
.food("ハンバーグ")
.drink("赤ワイン")
.show();
}
可変長引数
Rustには、組み込みの可変長引数の機能は存在しない。
しかし、スライス、ベクター、マクロを使用することにより、同様の効果を得ることができる。
スライスを使用した可変長引数
以下の例では、スライスを引数として受け取ることで、複数の値を処理している。
fn dinner_menu(items: &[&str]) {
for item in items {
println!("{}", item);
}
}
fn main() {
let menu = ["定食", "お茶", "ゼリー"];
dinner_menu(&menu);
}
// 出力
定食
お茶
ゼリー
ベクタを使用した可変長引数
以下の例では、ベクタを使用して可変長の引数を実現している。
fn dinner_menu(items: Vec<String>) {
for item in items {
println!("{}", item);
}
}
fn main() {
let menu = vec!["定食".to_string(), "お茶".to_string(), "ゼリー".to_string()];
dinner_menu(menu);
}
// 出力
定食
お茶
ゼリー
マクロを使用した可変長引数
マクロを使用すると、より柔軟な可変長引数を実現できる。
macro_rules! print_items {
($($item:expr),*) => {
$(
println!("{}", $item);
)*
};
}
fn main() {
print_items!("定食", "お茶", "ゼリー");
}
// 出力
定食
お茶
ゼリー
関数ポインタとクロージャ
Rustでは、メソッドを変数に代入したり、メソッドの引数として関数を渡したり、メソッドの戻り値として関数を返すことができる。
これには関数ポインタやクロージャを使用する。
関数ポインタ
以下の例では、関数を引数として別の関数に渡している。
fn hello() {
println!("Hello, Rust");
}
fn callback_func(callback: fn()) {
callback();
}
fn main() {
callback_func(hello);
}
// 出力
Hello, Rust
クロージャ
クロージャは、無名関数であり、変数に代入したり、引数として渡すことができる。
fn main() {
let hello = || {
println!("Hello, Rust");
};
let callback_func = |callback: fn()| {
callback();
};
callback_func(|| println!("Hello, Rust"));
}
// 出力
Hello, Rust
関数内関数 (ネストした関数)
Rustでは、メソッドの中で別のメソッドを定義することができる。
以下の例では、外側のメソッドとその中で定義される内側のメソッドを定義する。
ここでは、外側のメソッド名をouter_func、内側のメソッド名をinner_funcとする。
外側のメソッドでは、2つの引数を加算して、内側のメソッドでは、2つの引数を加えて10倍して、それを出力している。
fn outer_func(a: i32, b: i32) {
fn inner_func(c: i32, d: i32) -> i32 {
(c + d) * 10
}
let out_value = a + b;
let in_value = inner_func(a, b);
println!("{} {} OutValue = {} InValue = {}", a, b, out_value, in_value);
}
fn main() {
outer_func(3, 4);
}
// 出力
3 4 OutValue = 7 InValue = 70
※注意
内側の関数は、外側の関数のスコープ内でのみ使用できる。
内側の関数は、外側の関数の変数にアクセスできない。(クロージャを使用すればアクセス可能)