Prompt
構造体にある関数は、
&selfがあればメソッドで、なければただの”構造体に紐づいた関数”?
その通り!君の理解は完璧だぜ。情報工学的に言うと、それらは 「メソッド(Methods)」 と 「関連関数(Associated Functions)」 という名前で明確に区別されているんだ。
Rustのこの設計は、オブジェクト指向言語の「クラス」と、関数型言語の「名前空間」の良いとこ取りをしたような形になっているのが面白いポイントだね。
1. 関連関数:構造体という「名前空間」に住む関数
&self(あるいは &mut self や self)を第一引数に持たないものは、インスタンスではなく 「型そのもの」 に紐づいている。
-
呼び出し方:
StructName::function_name()(ダブルコロン::を使う) -
主な用途: コンストラクタ(
newなど)。 -
思想: その型に関連する便利機能を、グローバルに散らかさず、構造体の名前の下に整理してまとめる(カプセル化)ために使うんだ。
Rust
struct User {
id: u32,
}
impl User {
// 関連関数(コンストラクタ)
fn new(id: u32) -> Self {
User { id }
}
}
// インスタンスがなくても呼べる!
let u = User::new(1);
2. メソッド:インスタンスの「振る舞い」
第一引数に self 関連のキーワードがあるものは、特定のインスタンスの状態にアクセスできる。
-
呼び出し方:
instance.method_name()(ドット.を使う) -
主な用途: そのオブジェクトのデータを読み取ったり、書き換えたりする「操作」。
-
魔法の糖衣構文:
u.show()と書くと、内部的にはUser::show(&u)という形に変換されて実行されるんだ。
Rust
impl User {
// メソッド(読み取り)
fn show(&self) {
println!("User ID: {}", self.id);
}
}
let u = User::new(42);
u.show(); // ドットで呼べる!
3. 💡 見落とされがちな視点:self のバリエーション
実は self にはいくつか種類があって、これが Rust の所有権システムを象徴しているんだぜ。
-
&self: 不変の参照。中身を覗くだけ(最も一般的)。 -
&mut self: 可変の参照。中身を書き換える。 -
self: 所有権を奪う。そのメソッドを呼んだ後、そのインスタンスは使えなくなる(「自分を破壊して別の何かに変換する」時などに使う)。
🛠️ 専門学生的なマニアック知識:関数ポインタとしての共通性
「メソッド」も「関連関数」も、コンパイル後のバイナリレベルで見れば、実はどちらも 「第一引数が特殊なだけのただの関数」 なんだ。
Rust
// 実はこういう呼び方もできる(あまりやらないけど)
User::show(&u);
このように、Rustは「オブジェクト指向っぽく見えるドット表記」を提供しつつ、その実体は非常にシンプルで予測可能な「関数」として扱っている。これが、以前話した 「Safe Rustは数学的に証明しやすい」 という一貫性に繋がっているんだね。
🏁 まとめ
-
selfなし: 関連関数。型::関数()で呼び、主に生成(new)に使う。 -
selfあり: メソッド。インスタンス.関数()で呼び、状態の操作に使う。
君が garden.asappy.xyz で公開している Quartz のように、情報を整理する時も「これは型全体の話か?それとも特定のデータの話か?」を意識すると、コードの可読性がグッと上がるぜ!
次は、この self を使った面白いパターン、「メソッドチェーン(Builderパターン)」 の作り方を覗いてみる?😊✨
Would you like me to show you how to return Self from a method to enable a fluent API like user.set_name("Alice").set_age(20)?