Rustでオブジェクトに関数を実装したい


Rustでオブジェクト指向的に関数を実装する方法を自分が読みやすいようににかんたんにまとめた。
間違っている可能性が大きいので指摘をお願いします。
**2022/06/07:間違っている部分が有りましたので修正しました。**

[オブジェクト指向経験者のためのRust入門](https://qiita.com/nacika_ins/items/cf3782bd371da79def74)の**impl**までを参考にして必要以上に細かく書いている感じです。
[Rustで"this is an associated function, not a method"のエラーが出たのでメソッドと関連関数について調べてみた](https://qiita.com/Papillon6814/items/58bccd6cb821601232db)も参考にしています。

## Struct = Class のような雰囲気
```rust
pub struct Class1 { //パブリックなstructを作成
	num: i32,
	is_true: bool
}
```
クラスに定義される属性（変数）は`struct`ブロックの中で書くことができる

## 関連関数を書くときはimpl
```Rust
impl Class1 {
	pub fn new(is_true: bool, num: i32) -> Self {
		println!("You will be able to use Class1 object I will return.");
		return Class1 { //ここのreturnは省略可,Class1はSelfとすることも可能
		    num: num,
			is_true: is_true,
		}
	}
	pub fn func1(&self, num: i32){
	    println!("You called this function with number: {}", num)
    }
}
```
クラスを定義したとき、そのクラスのオブジェクトを作るために`new`関数が必要になることがあるだろう。
この`new`関数は`println()`メソッドで説明を出力した後に渡された2つの情報`num`と`is_true`の2つを使ってClass1を返す。
このように`impl`キーワードを使用してオブジェクトへ実装した関数のことを**関連関数**という。

### -> Class1のnew関数関係を一文目から説明していく。
１. `impl Class1`でClass1に関数を実装できる。
   `impl`はおそらくimplementationの略であり、実装するということである。
   `impl`の後に関数を実装したい構造体(struct)を書く。
   
２. 実装したい関数を書く。
   標準はスコープがprivateなため外部から呼び出すことが出来ないので、`pub`キーワードを冒頭につけ外部から呼び出せるようにする。`new`関数なので呼び出せないとまずいだろう。
   
   このとき、返り値がユニット型(`()`で表される空のタプル-> 要するに何も返すものがない)でないので、返す値の型を宣言する必要がある。

:::note info
**2022/06/07,訂正** 
コメント欄で指摘を頂きました。C++もどきを書いてしまっていました。
間違った表記を参考にしてしまった方がいらっしゃいましたら申し訳ないです。指摘で書いていただいたコードを使用させていただきます。
@yaito3014さん、ありがとうございました。
:::

   C++では関数名(`func1`など)の前に返り値を書いていた(次のように)が、

```C++
class ClassName {
 public:
  int func1(int num) {
    printf("You called this function with number: %d\n", num);
    return num;
  }
};
```
Rustでは矢印表記の後に明記する必要がある。

```Rust
		pub fn func1(&self, num: i32) -> i32 { //[-> i32]の表記で返り値の型がi32であることを宣言している
		    println!("You called this function with number: {}", num);
		    return num; //returnは省略可
	    }
```

３. `println()`マクロで`new`関数実行時にコンソールへ文字出力をする

４. `return Class1` で返すClass1オブジェクトを作っている。`Class1`クラスの関数で`Class1`オブジェクトを返すので、`return Self`と書くこともできる。

### -> オブジェクトのメソッドと関連関数
まず、関連関数とは`impl`キーワードでオブジェクトに対して実装された関数のことであった。
ここでこの2つの関連関数の違いを見てみよう。

```Rust
	pub fn func1(&self, num: i32) -> i32 {
	    println!("You called this function with number: {}", num);
	    return num; //returnは省略可
    }
    pub fn func2(num: i32) -> i32 {
	    println!("You called this function with number: {}", num);
	    return num; //returnは省略可
    }
```

これら2つの関数行う処理で違う部分は、第一引数に`&self`を取るか否かである。
ここで引数に`&self`を取る関連関数func1を、**メソッド**と呼ぶ。

ここでメソッドとただの関連関数の違いは、インスタンスから呼び出すことができるか否かだ。
それぞれインスタンスから呼び出してみると、
```Rust
println!("{}",cls1_instance.func1(32));
println!("{}",cls1_instance.func2(32));
```

```rust_errors
26 |     println!("{}",cls1test.func2(32));
   |                            ^^^^^ this is an associated function, not a method
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in an impl for the type `Class1`
  --> src/main.rs:18:5
```
2つ目の関数でエラーが発生し、エラーメッセージから`func2`はメソッドでないため、インスタンスから呼び出すことが出来ないから発生したエラーだとわかる。

ただの関連関数は`クラス名::関数名()`のようにして呼び出すことはできるが、`インスタンス.関数名()`と呼び出すことは関連関数では出来ず、メソッドとして定義する必要があることに注意する必要がある。

#### メソッドの第一引数&self
メソッドを作るためには第一引数を`&self`としなければならなかったが、この`&self`はメソッドが呼び出されたインスタンスへの参照である。
このことを確かめるため、次のコードを実行してみる。
```Rust
pub struct Class1 { //パブリックなstructを作成
	num: i32,
	is_true: bool
}

impl Class1 {
	pub fn new(is_true: bool, num: i32) -> Self {
		println!("You will be able to use Class1 object I will return.");
		return Self {
		    num: num,
			is_true: is_true,
		}
	}
	pub fn func1(&self, num_arg: i32){ //返り値はユニット型になるので->などは不要
	    println!("This function was called by you with number: {}.\nAnd, The num attribute of the instance used to call this function is {}", num_arg, self.num);
    }
}
fn main(){
    let cls1test = Class1::new(true, 32); //第2引数で32を指定しているのでnum属性は32となる。
    cls1test.func1(50); //呼び出す際の引数では50を指定する。
}

```

```output
You will be able to use Class1 object I will return.
This function was called by you with number: 50.
And, The num attribute of the instance used to call this function is 32
```
出力結果とコードからメソッドが呼び出されたインスタンス(`cls1test`)の参照が&selfであることがわかる。