3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

メソッドと関数の違い

Rustでは「メソッド」と「関数」は明確に区別されます。

メソッドは関数と似ており、fnキーワードを使って宣言します。ただし、メソッドは必ず何かしらのオブジェクト(構造体や列挙型などを指します)に紐づけられます。

メソッドを実装するときはimplキーワードを使用します。例えば構造体にメソッドを実装したい場合は、impl 構造体名 { ... }とします。

メソッドの引数

メソッドの第一引数は必ず実装されているインスタンス自身になります。その引数名はselfで型はSelfと表現されます。このselfは、メソッドが基づく構造体のインスタンスを指します。例えばPersonという構造体にメソッドを定義した場合、そのメソッドの第一引数のselfPerson型になります。インスタンスのメソッドを呼び出すと、そのインスタンスの情報を参照したり、更新したりできます。

また、fn メソッド名(self: Self)と書く代わりにfn メソッド名(self)というシンタックスシュガーも用意されています。

更新する際は、&mut selfと書く必要があります。

struct Person {
    name: String,
    age: u8,
}

impl Person {
    fn greet(self) {
        println!("Hello, my name is {}.", self.name);
    }
    
    fn birthday(&mut self) {
        self.age += 1;
        println!("Happy birthday! I'm now {} years old.", self.age);
    }
}

selfだけでなく、第二引数以降で追加の引数を取るメソッドも定義できます。

impl Person {
    fn update_name(&mut self, new_name: String) {
        self.name = new_name;
        println!("My name is now {}.", self.name);
    }
}

メソッドの呼び出し

インスタンス名.メソッド名()の形で呼び出します。第一引数のselfは自動的に渡されるので、呼び出し時に明示する必要がありません。すなわち、selfしか引数を取らない場合は、()だけで大丈夫です。第二引数以降がある場合、第二引数からメソッドに渡します。

fn main() {
    let mut person = Person {
        name: String::from("Alice"),
        age: 30,
    };

    person.greet(); // "Hello, my name is Alice."
    person.birthday(); // "Happy birthday! I'm now 31 years old."
    person.update_name(String::from("Bob")); // "My name is now Bob."
}

構造体にロジックを持たせるという点で、強力なオブジェクト指向を実現できそうな気がします。

関連関数

メソッドの定義時には「第一引数はselfである」と書きましたが、そうでない関数を書くことも可能です。すなわち、第一引数がselfでない関数を定義でき、それは(メソッドではなく)関連関数と呼ばれます。

関連関数はあくまで関数であり、インスタンスではなく構造体そのものに紐づきます。呼び出すときは型名::関連関数名で呼び出します(String::newやVector::newのようなものです)。

impl Person {
    // 関連関数
    fn new(name: String, age: u8) -> Self {
        Self { name, age }
    }
}

主なユースケースですが、構造体のコンストラクタに利用することが考えられます。構造体は構造体名 { ... }で宣言できますが、フィールドを個別に指定させるのが手間になります。生成時に指定したいフィールドとそうでないフィールド(自動計算したい、任意の値を取れない)がある場合は、そのロジックをコンストラクタとして定義しておき、そのコンストラクタを通してインスタンスを生成させるパターンが有効です。

fn main() {
    let person = Person::new(String::from("Charlie"), 25);
    person.greet(); // "Hello, my name is Charlie."
}

関連関数はJavaでいうstaticメソッドのようなものでしょうか。上手に使い分けたいですね。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?