【Swift】型の構成要素〜サブスクリプト〜

#サブスクリプト とは

サブスクリプトとは、配列や辞書などのコレクションの
要素へのアクセスを統一的に表すための文法です。

下記のような場面で使いましたね！

```swift

let array = [1, 2, 3]
let firstElement = array[0]   // 1

let dictionary = ["a": 1, "b": 2, "c": 3]
let elementA = dictionary["a"]   // 1
```

##定義方法

サブスクリプトを定義するには、
**subscriptキーワード**に続けて引数と戻り値の型を指定し、{ }内にセッタやゲッタを定義します。

引数や戻り値の型の定義方法は関数と同じですが、
サブスクリプトでは全ての外部引数名がデフォルトで`_`になっています。

また、ゲッタとセッタは、
コンピューテッドプロパティのものと同様です。

形としては次のようになります。

```swift

subscript(引数) -> 戻り値の型 {
   get {
      return文で値を返す処理
   }
   
   set {
      値を更新する処理
   }
}
```

サブスクリプトを使用するには、
型のインスタンスが代入された変数や定数に[ ]で囲まれた引数をつけて、
`変数名[引数]`のように記述します。

値の取得時にはゲッタが呼ばれ、
値の更新時にはセッタが呼ばれます。

サンプルコードを書いてみました。

`print(arrayInt[1])`は値の取得なのでゲッタが使用されます。
subscriptの引数indexには１が入り、array[１]の値を返しています。

`arrayInt[1] = 4`は値の更新なのでセッタが使用されます。
`array[index] = newValue`のnewValueは新しい値なので４が該当します。

```swift

struct ArrayInt {
    var array: [Int]
    
    subscript(index: Int) -> Int {
        get {
            return array[index]
        }
        
        set {
            array[index] = newValue
        }
    }
}

var arrayInt = ArrayInt(array: [1, 2, 3])
print(arrayInt[1])

arrayInt[1] = 4
print(arrayInt[1])

実行結果
2
4
```

引数が複数ある場合も同様の流れになります。
二次元配列に変えただけなので特別難しい処理は行っていません。

```swift

struct ArrayInt {
    var array: [[Int]]
    
    subscript(row: Int, column: Int) -> Int {
        get {
            return array[row][column]
        }
        
        set {
            array[row][column] = newValue
        }
    }
}

var arrayInt = ArrayInt(array: [
                            [1, 2, 3],
                            [4, 5, 6],
                            [7, 8, 9]
])
print(arrayInt[1,1])

実行結果
5
```

##セッタの省略

コンピューテッドプロパティと同様に、
**サブスクリプトでもゲッタの定義は必須になります。**

しかし、セッタの定義は任意になっています。
セッタが存在しない場合は、getキーワードと{ }を省略して記述することもできます。

セッタを省略した場合のコードは下記のようになります。

```swift

struct ArrayInt {
    var array: [Int]
    
    subscript(index: Int) -> Int {
        return array[index]
    }
}

var arrayInt = ArrayInt(array: [1, 2, 3])
arrayInt[1]   // 2
```

セッタが省略されているにも関わらず、
値の更新を行おうとするとコンパイルエラーになります。

```swift

struct ArrayInt {
    var array: [Int]
    
    subscript(index: Int) -> Int {
        return array[index]
    }
}

var arrayInt = ArrayInt(array: [1, 2, 3])
arrayInt[1]   // 2
arrayInt[1] = 4   // コンパイルエラー
```

エラー内容：`Cannot assign through subscript: subscript is get-only`
和訳：subscriptで割り当てることはできません：subscriptは取得専用です
(subscriptを下付き文字と略していたのでそこだけsubscriptに戻しました。)

##オーバーロード
メソッドと同様にサブスクリプトもオーバーロードを行えます。

異なる型の引数や戻り値をとる同名のサブスクリプトを複数用意すれば
その時の処理に応じてサブスクリプトを切り替えることができます。

**例えば、Array\<Element>型でもサブスクリプトがオーバーロードされています。**

Int型を引数にとってElement型の要素を返すサブスクリプトと、
Range\<Int>型を引数に撮ってArraySlice\<Element>型の、
スライスを返すサブスクリプトが提供されています。

**スライスとはコレクションの一部を表すものです。**

```swift

let array = [1, 2, 3, 4]
let element = array[0]   // Element
let slice = array[0...2]   // ArraySlice<Element>
```

以上がサブスクリプトの説明になります。

配列の型を定義する際に必要な知識になると思うので
覚えておいて損はしないと思います。

データなどを扱う際に配列が関わってくるイメージがあるので、
私もしっかりと理解していつでも使えるようにしておこうと思います！

他にも型の構成要素について記載している記事がありますのでぜひそちらもご覧ください！

・[【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/dfe5be6ed494ceae1da0)
・[【Swift】型の構成要素〜エクステンション〜](https://qiita.com/onishiApp/items/c7e407fc6aa6e922a7da)
・[【Swift】型の構成要素〜型のネスト〜](https://qiita.com/onishiApp/items/040019f1a00826b5c9e5)

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