Rustまとめ-その参-(随時更新)

# Rustまとめ-その参-(随時更新)

## これまでのまとめリンク

- [Rustまとめ-その壱-(随時更新)](https://qiita.com/eisuke114/items/4fa49a2d7f181f04a5de)
- [Rustまとめ-その弐-(随時更新)](https://qiita.com/eisuke114/items/693c8b5628cfc2664d30)

## 構造体上にメソッドを定義
```
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
//implキーワードをつけて構造体上にメソッドを定義
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    
    //Rectangleのareaメソッドを使いu32の値を返してもらう
    println!(
        "The area of the rectangle is {} square pixels.",
        rect1.area()
    );
}
```
`impl`とは実装させるキーワードとなります。areaメソッドの引数が&selfになっているのは型が`Rectangle`だと把握しているからです。 
## 複数のメソッドを実装
```
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }

    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}

fn main() {
    let rect1 = Rectangle { width: 30, height: 50 };
    let rect2 = Rectangle { width: 10, height: 40 };
    let rect3 = Rectangle { width: 60, height: 45 };

    // rect1と比べて大きいか小さいか
    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
}
```
`impl`ブロックを分けることもできます。
```
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
```
まとめたものとまったく同じことになります。
## Enumを定義する方法
```
enum LikeFruit {
    Banana,
    Apple
}
```
## Enumのインスタンス生成
```
let jim = LikeFruit::Banana;
let Michael = LikeFruit::Apple; 
```
## 関数の引数にEnumをとる方法
```
fn sample(what_fruit: LikeFruit){}

fn main(){
    let s1 = sample(LikeFruit::Banana);
}
```
## StructのフィールドにEnumを定義する方法
```
enum LikeFruit {
    Banana,
    Apple,
}

struct UserInfo {
    Fruit: LikeFruit,
    Name: String,
}

let User1 = UserInfo {
    Fruit: Fruit::Banana,
    Name: String::from("Jim"),
};
```
## Enumに直接データを格納する
```
enum LikeFruit {
    Banana(String),
    Apple(String),
}
```
```
enum LikeFruit {
    Banana(u8,u8,u8),
    Apple(String),
}

let s2 = LikeFruit::Banana(10,2,3);
```
## match制御フロー演算子とは
ある値と`match`内のパターンと順番に比較します。パターンに値がマッチしたらそれに紐づけられたコードを実行します。
ここでいう値は引数に入れるもので、パターンは`match`スコープ内の事です。
```
enum Shop{
    Banana,
    Game,
    Book,
    Cable,
}

fn how_match(shop: Shop) -> u32 {
    match shop{
        Shop::Banana => 2,
        Shop::Game => 10,
        Shop::Book => 5,
        Shop::Cable => 3,
    }
}

fn main() {
    let s = how_match(Shop::Banana)
    
    plintln!("その商品の値段は、{}ドルです。",s);
    
    //出力結果
    //その商品の値段は、2ドルです。
}
```
`how_match`関数の引数に入ったものがBananaで2という値を返す行動を行います。
## match演算子内のパターンには自由にコードが書き込める
```
enum Shop{
    Banana,
    Game,
    Book,
    Cable,
}

fn how_match(shop: Shop) -> u32 {
    match shop{
        Shop::Banana => {
            plintln!("その商品の値段は、2ドルです。");
        },
        Shop::Game => 10,
        Shop::Book => 5,
        Shop::Cable => 3,
    }
}

fn main() {
    how_match(Shop::Banana)
    //出力結果
    //その商品の値段は、2ドルです。
}
```
## match演算子内のパターンにenumを紐づけする
```
#[derive(Debug)] 
enum  Prefecture{ //何県の物か
    Aomori,
    Iwate,
    // ... などなど
}

enum Shop{
    Banana(Prefecture),
    Game,
    Book,
    Cable,
}

fn how_match(shop: Shop) -> u32 {
    match shop{
        Shop::Banana(prefecture) => {
            println!("このバナナは{:?}県さんです。",prefecture);
        },
        Shop::Game => 10,
        Shop::Book => 5,
        Shop::Cable => 3,
    }
}

fn main() {
    how_match(Shop::Banana(Prefecture::Aomori))
    //出力結果
    //このバナナはAomori県さんです。
}
```
## match演算子でOption<T>を使い複雑なパターンを作る
```
fn get_num (x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 10),
    }
}

let ten = Some(10);
let eleven = get_num(ten);
let none = get_num(None);
```
## match演算子でどんな値でもマッチするキーワード
```
let some_u8_num = 0u8;
match some_u8_num {
    1 => println!("one"),
    3 => println!("three"),
    5 => println!("five"),
    7 => println!("seven"),
    _ => (),
}
```
## if letで簡潔なにmatch式を書く
```
if let Nom(4) = some_u8_num {
    println!("four");
}
```
## if letでmatch式の_に当たる部分をelseに置き換える
```
#[derive(Debug)] 
enum  Prefecture{ //何県の物か
    Aomori,
    Iwate,
    // ... などなど
}

enum Shop{
    Banana(Prefecture),
    Game,
    Book,
    Cable,
}

//match式の場合
let mut count = 0;
match shop {
    Shop::Banana(prefecture) => println!("このバナナは{:?}県産です。",prefecture),
    _ => count +=1,
}

//if letの場合
let mut count = 0;
if let Shop::Banana(prefecture) => shop {
    println!("このバナナは{:?}県産です。",prefecture);
} else {
    count += 1;
}
```