【Swift】型の構成要素〜メソッド〜

#メソッド とは
メソッドは型に紐付いた関数になります。

型のインスタンスが持っている機能（振る舞い）を実現するために使用されます。


##定義方法
メソッドを定義する方法は、型の定義の内部でfuncキーワードを使用します。
**メソッドの名前や引数、戻り値の文法は関数と同じです。**

```swift

func メソッド名(引数名: 引数の型) -> 戻り値の型 {
    メソッド呼び出し時に実行される文
}
```

メソッドを呼び出すには型のインスタンスが代入された変数や定数に、
. (ドット)とメソッド名と( )をつけて、`変数名.メソッド名(引数)`のように書きます。

**メソッドに複数の引数が必要だった場合は、
, (カンマ)で区切って複数の引数を記述します。**

２つの引数を必要とするメソッドの例を書いてみました。

```swift

struct Message {
    func hello(name: String, message: String) {
        print("\(name)さん、\(message)")
    }
}

let sample = Message()
sample.hello(name: "田中", message: "こんにちは")
sample.hello(name: "斎藤", message: "さようなら")

実行結果
田中さん、こんにちは
斎藤さん、さようなら
```

##紐づく対象と分類

プロパティと同様に、メソッドにも型のインスタンスに紐付いた**インスタンスメソッド**と、
型自身に紐付いた**スタティックメソッド**が存在します。

###インスタンスメソッド
インスタンスメソッドは、先ほども記載した通り、型のインスタンスに紐付いたメソッドです。
単にメソッドという時はインスタンスメソッドを指すことが多いと思います。

**funcキーワードで定義したメソッドは、
デフォルトではインスタンスメソッドになります。**

インスタンスメソッドはインスタンスに紐付いているので、
異なるインスタンスでは異なった結果を返します。

定数sample1とsample2を宣言しそれぞれを同じ型でインスタンス化しました。

この時どちらも同じプロパティやメソッドを持つ訳ですが、
**インスタンスメソッドにインスタンスプロパティなので中身の値は異なります。**

```swift

struct Sample {
    var name: String
    var message: String
    
    init(name: String, message: String) {
        self.name = name
        self.message = message
    }
    
    func say() {
        print("\(message) \(name) !")
    }
}

let sample1 = Sample(name: "Tanaka", message: "Hello")
let sample2 = Sample(name: "Watabe", message: "Good bay")

sample1.say()
sample2.say()

実行結果
Hello Tanaka !
Goodbay Watabe !
```

###スタティックメソッド
スタティックメソッドは先ほども記載しましたが、
**型自身に紐付くメソッドでありインスタンスに依存しない処理を行います。**

スタティックメソッドを定義する方法は、
メソッドの定義の先頭に**staticキーワード**を追加して定義します。

スタティックメソッドを呼ぶ際には、
`型名.メソッド名(引数)`の形で呼ぶ必要がります。

他の処理は、特に難しい処理は行っていないので説明は省きます。

```swift

struct Proverb {
    static var word = "早起きは三文の徳"
    
    static func changeWord(word: String){
        self.word = word
    }
    
    let plusWord = "今日のことわざは"
    var getWord: String {
        return "\(plusWord)、\(Proverb.word)"
    }
}

let proverb = Proverb()

print(proverb.getWord)
print("---")

Proverb.changeWord(word: "猿も木から落ちる")
print(proverb.getWord)

実行結果
今日のことわざは、早起きは三文の徳
---
今日のことわざは、猿も木から落ちる
```

##オーバーロード
オーバーロードとは、異なる型の引数や戻り値をとる**同名のメソッド**を複数用意し、
引数に渡される型や戻り値の代入先の型に応じて実行するメソッドを切り替える手法です。


**引数の型や戻り値の型が異なるものの、
中身の処理が似たメソッドを定義する際に便利な機能です。**

オーバーロードすることにより、
呼び出し側にそれらの違いを意識させないという用途で使われます。

###引数によるオーバーロード

引数によってメソッドをオーバーロードするためには、
引数の型が異なる同名のメソッドを複数定義します。

サンプルコードの実行結果から実行されるメソッドが切り替わっているのがわかります。

```swift

struct Sample {
    func test(a: Int) {
        print("Int : \(a)")
    }
    func test(a: String) {
        print("String: \(a)")
    }
}

let sample = Sample()
sample.test(a: 123)
sample.test(a: "abc")

実行結果
Int : 123
String: abc
```

###戻り値によるオーバーロード

戻り値によってメソッドをオーバーロードするには、
戻り値の型が異なる同名のメソッドを複数定義します。

戻り値の型によってオーバーロードする場合は、
**戻り値の代入先の型により、実行されるメソッドが変わります。**

しかし、戻り値の型が推論できない場合は、
実行するメソッドが決定できないためコンパイルエラーになります。


```swift

struct Sample {
    let intValue = 123
    let stringValue = "abc"
    
    func getValue() -> Int {
        return intValue
    }
    
    func getValue() -> String {
        return stringValue
    }

}

let sample = Sample()
let intValue: Int = sample.getValue()   // 123
let stringValue: String = sample.getValue()   // abc
let value = sample.getValue()   // コンパイルエラー
```

エラー内容：`Ambiguous use of 'getValue()'`
和訳：'getValue（）'のあいまいな使用

以上がメソッドの説明になります。

関数を定義する時とほぼ同じなのでそんなに難しい内容ではないのかなと思いますが、
オーバーロードは新しい知識でしたので記事を書いていて勉強になりました！

使いどころは今のところピンときませんが、
結構大事な知識なのかなとは思ったので忘れないようにしたいです。

他にも、型の構成要素に関する記事を載せていますのでぜひご覧ください！

・[【Swift】型の構成要素〜型の基本〜](https://qiita.com/onishiApp/items/759c96bdbaebb2303a94)
・[【Swift】型の構成要素〜プロパティ前編〜](https://qiita.com/onishiApp/items/db19c212ce6eeb42ef9e)
・[【Swift】型の構成要素〜イニシャライザ〜](https://qiita.com/onishiApp/items/78a0bd93708384b5e487)
・[【Swift】型の構成要素〜サブスクリプト〜](https://qiita.com/onishiApp/items/281daff3d84c13bdd586)
・[【Swift】型の構成要素〜エクステンション〜](https://qiita.com/onishiApp/items/c7e407fc6aa6e922a7da)
・[【Swift】型の構成要素〜型のネスト〜](https://qiita.com/onishiApp/items/040019f1a00826b5c9e5)

最後までご覧いただきありがとうございました。