delegateの自分なりの解釈 (Swift)

# 概要
今回はSwiftでdelegateを使ってみようということで記事を書かせていただきます.

# 環境
Swift 4.2

# Amazonと551と私
デリゲートとはなんぞやの前に、まずあるストーリーを想像してみてください.

あなたは今 とある人間Aくんです.

Aは今 とてもつもなく551が食べたいです.

![d001-main.jpg](https://qiita-image-store.s3.amazonaws.com/0/300444/3bf42a0c-4e87-5971-1ac6-d046e75270a5.jpeg)

美味しそうですね...

**しかし！！！**

Aは今**東京に住んでいます...**

本場の肉まん551を食べるには大阪まで行かないといけません. ~~(ほなイコカ)~~

**そこで**

**Amazonに配達をお願いします**

![IMG_0952.PNG](https://qiita-image-store.s3.amazonaws.com/0/300444/2b250a04-14b9-d415-a160-bf9564b77e9e.png)

Amazonに**頼めば**仮に東京にいても美味しい551が食べられるのです.

つまり、自分がやりたくない処理を他の誰かにお願いし任せること(移譲)がdelegateの役割です.

では、delegateの解説を始めていきたいと思います.

# delegateについて
では`delegate`とはなんぞやということで.
> あるクラスから処理の一部を他のクラスに任せたり、他のクラスへメッセージを送る等の目的でよく使われるデザインパターン
> 引用:http://nukenuke.hatenablog.com/entry/2015/09/17/120749



とのことです.つまり**処理をお願いすること**です. 難しい言葉で言うと`移譲`です.残念ながら僕は最初その言葉を聞いてあまりピンと来ませんでした.

なんにせよ具体的な使い方を覚えたほうが早いと思うので先ほどの話を用いてコードを書いていきましょう

`ButamanPersonInTokyo`をA君として、`Amazon`クラスを用いて考えていきましょう.

### `ButamanPersonInTokyo`で`Amazon`に`gogoichi`という変数を`delegate`を用いて送ってみる(`PlayGround`)

##### STEP0.`Gogoichi`クラスと`GogoichiKind`を実装

**本題とは関係ない**ので`PlayGround`にコピペでOKです.

```swift
enum GogoichiKind: String {
    
    case Butaman = "豚まん"
    case Dango = "団子"
    case Gyoza = "餃子"
}

class Gogoichi {
    
    var price: Int {
        
        switch kind {
        case .Butaman:
            return 170
        case .Dango:
            return 30
        case .Gyoza:
            return 30
        }
    }
    
    var kind: GogoichiKind = .Butaman
}
```



##### STEP1. protocolの宣言

```swift
protocol SendGogoichi {
    func send(gogoichi: Any) -> Void
}
```

ポイント. 呼ばれるメソッドは`protocol`の中で**定義のみ**しないといけない. (処理は書かないと言う意味です)

##### STEP2. `ButamanPersonInTokyo`の宣言. delegateの宣言

```swift
class ButamanPersonInTokyo {
    
    var delegate: SendGogoichi?
}
```

ポイント. `var delegate: SendGogoichi?`を処理を**お願いする側**で宣言しておく

##### STEP3. `Amazon`の宣言. protocolを継承. 同時にプロトコルのメソッドを宣言.

```swift
class Amazon: SendGogoichi {
    
    func send(gogoichi: Gogoichi) {
    }
}
```

ポイント. `SendGogoichi`プロトコルを**処理を任された側**で継承しておく

##### delegateを設定する.

delegateを設定するとは**どのクラスが処理をお願いしてどのクラスが処理を任されるのか**を決めることです。
お願いされる側は`protocol`を**継承**している方でした.`Amazon`の方です.
お願いをする側は`delegate`を**宣言**している方でした.`ButamanPersonInTokyo`の方です.

**delegateの宣言の仕方は**

```swift
var delegate: SendGogoichi?
```

でした. この`SendGogoichi`はプロトコルである必要があります.

**宣言したdelegateにお願い先を代入**

```swift
delegate = Amazon()
```

これを書いてあげればいいのですが, `delegate`は代入してあげないと初期値が`nil`なので`Optional Chaining`した時にメソッドが呼ばれません.

```swift
delegate: SendGogoichi? //nilが入っている
delegate?.send(gogoichi: gogoichi) //sendメソッドはdelegateがnilなので呼ばれない.
```

なので

```swift
delegate = Amazon()
delegate?.send(gogoichi: gogoichi)
```
のように`delegate?.send(gogoichi: gogoichi)`よりも前に`delegate`に値をいれてあげる必要があります.

##### `ButamanPersonInTokyo`が`Amazon`に`gogoichi`をお願いするメソッドを書く.

```swift
func orderButaman() {

    let gogoichi: Gogoichi = Gogoichi()
    gogoichi.kind = .Butaman
    delegate?.send(gogoichi: gogoichi) // ここで処理をお願いしている
}
```

この`orderButaman`メソッドで`delegate?.send`が呼ばれるという形になっています.

##### 任される側のクラス(`Amazon`)で送信する処理を実装する.

```swift
func send(gogoichi: Gogoichi) {
        
    for _ in 0...2 {
        sleep(1)
        print("配達中...")
    }
    print("\(gogoichi.kind)の送信を完了しました.値段は\(gogoichi.price)円です.")
}
```

`sleep(1)`は配達には時間がかかることを想定して処理に時間をかけてます.

##### インスタンス化

```swift
let butamanPerson = ButamanPersonInTokyo()

butamanPerson.delegate = Amazon()

butamanPerson.orderButaman()
```

### 全体のコード

```swift
import UIKit
import Foundation

enum GogoichiKind: String {
    
    case Butaman = "豚まん"
    case Dango = "団子"
    case Gyoza = "餃子"
}

class Gogoichi {
    
    var price: Int {
        
        switch kind {
        case .Butaman:
            return 170
        case .Dango:
            return 30
        case .Gyoza:
            return 30
        }
    }
    
    var kind: GogoichiKind = .Butaman
}

protocol SendGogoichi {
    
    func send(gogoichi: Gogoichi) -> Void
}

class Amazon: SendGogoichi {
    
    
    func send(gogoichi: Gogoichi) {
        
        //
        for _ in 0...2 {
            sleep(1)
            print("配達中...")
        }
        print("\(gogoichi.kind)の送信を完了しました.値段は\(gogoichi.price)円です.")
        
    }
}

class ButamanPersonInTokyo {
    
    var delegate: SendGogoichi?
    
    func orderButaman() {
        
        let gogoichi: Gogoichi = Gogoichi()
        gogoichi.kind = .Butaman
        delegate?.send(gogoichi: gogoichi)
    }
}

let butamanPerson = ButamanPersonInTokyo()

butamanPerson.delegate = Amazon()

butamanPerson.orderButaman()
```

#### コンソール

<img width="515" alt="スクリーンショット 2018-11-25 2.02.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/300444/5d19d74d-c3f6-9845-ac90-cc7a63692773.png">

### なぜデリゲートを使うのか
薄々感づいた人もいると思いますが, これ**delegateなくても書けます.**

![IMGL8663171031_TP_V.jpg](https://qiita-image-store.s3.amazonaws.com/0/300444/e4a30207-ba30-f94a-5c7e-ef5564af59d7.jpeg)

`delegate`を使うメリットの１つとして**処理を任せた相手がどんなクラスであるのかを考えなくていい**という点があります.

今回は`delegate`のメリットはあまりありませんでしたが、もし**`Amazon`ではなく`大阪の友達`が`gogoichi`を送ってくれたらどうでしょう**

この実装の変更の流れをみていきます。

##### 　もし`delegate`を用いていなかったら

```swift
class ButamanPersonInTokyo {
    
    func orderButaman() {
        
        let gogoichi: Gogoichi = Gogoichi()
        gogoichi.kind = .Butaman
        Amazon().send(gogoichi: gogoichi) // ここ
    }
}
```

こうやって直接読んであげることになります.

これを大阪の友達に頼むと

```swift
class ButamanPersonInTokyo {
    
    func orderButaman() {
        
        let gogoichi: Gogoichi = Gogoichi()
        gogoichi.kind = .Butaman
        大阪の友達().send(gogoichi: gogoichi) // ここ
    }
}
```

こうなりますよね

**しかし**

###### `delegate`を用いると
`ButamanPersonInTokyo`はコードを変更する必要がありません.

```swift
class ButamanPersonInTokyo {
    
    var delegate: SendGogoichi?
    
    func orderButaman() {
        
        let gogoichi: Gogoichi = Gogoichi()
        gogoichi.kind = .Butaman
        delegate?.send(gogoichi: gogoichi)
    }
}
```

このままで大丈夫です.

インスタンス化した時に**delegateに入れる相手を変更すればいいんです**

```swift
class OsakaFriend: SendGogoichi {
    
    func send(gogoichi: Gogoichi) {
        
        for _ in 0...2 {
            sleep(1)
            print("配達中...")
        }
        print("\(gogoichi.kind)の送信を完了しました.値段は友達なので無料だよ.")
    }
}
```

```swift
let butamanPerson = ButamanPersonInTokyo()
butamanPerson.delegate = OsakaFriend()
```

#### コンソール
<img width="399" alt="スクリーンショット 2018-11-25 2.13.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/300444/a7eee508-6444-c66b-2bc5-9873dba46eae.png">

# まとめ
適当な話の下りでしたが`delegate`は理解できたでしょうか/
`delegate`を使うことで得られる

**`class`のように再利用できる**
**お願いする先を気にしなくて良い**

の２つの利点について考えてみました。

`class`のように再利用できる点については`Swift`を`オブジェクト指向`ならぬ`プロトコル指向`として捉える考えもあるようでプロトコルは重要なのではと感じています.


自分なり砕けて説明してみたのでもしここは違うよというところがあればアドバイスください。
最後まで読んでいただきありがとうございました！