【Swift】よく分からなかったdelegateについて整理してみた（初心者が初心者のために）

# そもそもdelegateってなんだ
## 言葉を調べてみる
delegateを辞書で調べてみると、

1．委任する
2．代表［代理］に立てる

という意味らしい。

なるほど、言葉の意味は分かった。<br><br>

## Swift的観点で調べる

では、Swiftにおいて、delegateってなんだ？ともう少し調べてみると、

「delegateとは、デザインパターンのひとつです。」

なんて出てきた。

なるほど、分からないようで分からない。<br><br>


## 分からんかったからさらに調べる

さらに調べていくと、TECHACADEMYにたどり着いた。
https://techacademy.jp/magazine/15055

ここでは、

『実際のイメージとしては「ある特定の事項について、問い合わせ先を指定する」操作と覚えておくと分かりやすいです。』

と書いてあった。<br><br>

delegate = 問い合わせ先とも書いてあって、これが一番理解しやすいような気がする。（なんとなく）


まあ、とりあえず実装してみないと分からないイメージつかないので、実装に移りたい。


# delegateを実装するために必要なもの

## 1.protocol
委任する処理をmethodとして定義する。これをデリゲートメソッドと呼ぶ。
言わば「仕様書」と言ったところ。

## 2.処理を委任するclass
デリゲートメソッドを使用して、処理の流れを記述する。

## 3.処理を委任されるclass
protocolで定義されたデリゲートメソッドを実装する。


# 実際に実装してみる

## 1.protocol
メソッドを定義する。

```swift:HorseDataProtocol.swift
protocol horseDataDelegate {
    
    func horseName() // 競走馬名
    func horseBirthYear() // 競走馬の誕生年
    func horseWinNumber() // 競走馬の勝利数
    func horseIsLeadingSire() // 競走馬の種牡馬状況
    
}
```

## 2.処理を委任するclass

今回はViewController内に実装した。


```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    var delegate: horseDataDelegate? //delegateを定義
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //使用するdelegateをここで呼び出す
        delegate = DeepImpact()
        
        //delegate内のメソッドを呼び出す
        delegate?.horseName()
        delegate?.horseBirthYear()
        delegate?.horseWinNumber()
        delegate?.horseIsLeadingSire()
    }
}
```

## 3.処理を委任されるclass
protocolに記載したメソッドを使用して記載する。

```swift:DeepImpact.swift
class DeepImpact: horseDataDelegate {
    
    func horseName() {
        print("Horse Name is Deep Impact")
    }
    
    func horseBirthYear() {
        print("Horse was born in 2002")
    }
    
    func horseWinNumber() {
        print("Horse won 12")
    }
    
    func horseIsLeadingSire() {
        print("Horse is Leading Sire")
    }
    
}
```

これでRunすると、こんな感じで出力される。

```:出力
Horse Name is Deep Impact
Horse was born in 2002
Horse won 12
Horse is Leading Sire
```

# 共通なメソッドをprotocolに用意する

ここでまとめても良かったが、もう少し突っ込んでみる。

horseDataDelegateのクラスをもう一つ作成してみた。

```swift:Orfevre.swift
class Orfevre: horseDataDelegate {
    
    func horseName() {
        print("Horse Name is Orfevre")
    }
    
    func horseBirthYear() {
        print("Horse was born in 2008")
    }
    
    func horseWinNumber() {
        print("Horse won 12")
    }
    
}
```

ViewControllerのdelegateもこれに伴って変更してみる。

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {
    
    var delegate: horseDataDelegate? //delegateを定義
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //delegate先を変更
        delegate = Orfevre()
        
        delegate?.horseName()
        delegate?.horseBirthYear()
        delegate?.horseWinNumber()
        delegate?.horseIsLeadingSire()
    }
}
```

これでRunすると、Orfevreクラスでエラーが出る。

```:出力
Type 'Orfevre' does not conform to protocol 'horseDataDelegate'
```

horseIsLeadingSireメソッドないよ！って言われてる。

基本的に**protocolに記載されているものは全部書かないといけない**。

が、共通でもいいメソッドがある時は、わざわざ全部のメソッドを書く必要もない.

そこで、protocolを少しだけ修正する。

```swift:HorseDataProtocol.swift
protocol horseDataDelegate {
    
    func horseName() // 競走馬名
    func horseBirthYear() // 競走馬の誕生年
    func horseWinNumber() // 競走馬の勝利数
    func horseIsLeadingSire() // 競走馬の種牡馬状況
    
}

extension horseDataDelegate {

    // このメソッドはデフォルトで実装しておく
    func horseIsLeadingSire() {
        print("Horse is not Leading Sire")
    }
}
```

共通で使用するメソッドは、このように、extensionで用意しておけばいい。

Orfevre.swift内のhorseIsLeadingSire()は、これをオーバーライドしているという形になる。

これでRunが通る。出力はこんな感じ。

```:出力
Horse Name is Orfevre
Horse was born in 2008
Horse won 12
Horse is not Leading Sire
```

本当は、もう少し書きたいことがあったけど、長くなりそうなので今回はここまでで。

## 最後に

今回作成したものはGithubに載せています。
https://github.com/taichi6930/SwiftDelegateSample

初めてQiitaに投稿してみました。
やはり文章を書くのは難しいですね。

とはいえ、自分の頭の中で整理しながら書くことができました。
これからも続けていきたいと思います。