【Swift】拡張(エクステンション)の使い方。クラスからデータ型まであらゆる機能を拡張する。(Swift 2.1、XCode 7.2)

2020年6月16日

拡張(エクステンション)とは

拡張(エクステンション)とは、既存のクラスや構造体、Enumからデータ型まであらゆるものに対して、名前はそのままにプロパティやメソッドを追加する機能である。

プロパティやメソッドを追加する機能といえば「継承」をイメージするが、「継承」はクラスのプロパティやメソッドを引き継いで新たなクラスを別名で作るのに対し、「拡張」は名前はそのままにプロパティやメソッドを追加することができるのが特徴である。

拡張は以下のように定義する。

 

以下のコードは作成した商品クラスを拡張して、税抜価格のプロパティと割引メソッドを追加した例である。残念なことにプロパティはComputedプロパティしか追加できない。Computedプロパティに関しては次の記事を参照されたし⇒「記事

 

拡張は定義を追加することはできるが、継承で使われるメソッドのオーバーライドを使うことはできない。つまり、拡張前クラスのメソッドの処理内容を修正したくてもできない。新しいメソッドを追加して対応するべし。

 

イニシャライザを追加する

拡張はイニシャライザを追加することができる。ただし、コンビニエンスイニシャライザのみ追加することができる。以下のコードは拡張クラスにコンビニエンスイニシャライザを定義し、コンビニエンスイニシャライザから、商品クラスの指名イニシャライザを呼び出す例である。

ちなみに、コンビニエンスイニシャライザはプロパティの初期化をすることはできないイニシャライザであり、他の指名イニシャライザを呼び出すことでプロパティを初期化する。あまり重要なことができないイメージだ。以下の例では、引数が1個でイニシャライザが呼ばれたときに、もう一つのプロパティ(id)をつけて本来のイニシャライザを呼び出している。

このように、拡張ではStoreadプロパティの追加、指名イニシャライザの追加をできなくすることで、クラスの根幹部分を壊されないようにしている。

拡張で追加したメソッドの注意事項

以下のコードのように、拡張で追加したメソッドはサブクラスでオーバーライドすることができない。拡張で追加したメソッドは見えないfinalが書かれていると考えるといい。

 

拡張とプロトコル

以下のコードのように、拡張にプロトコルを適用することができる。これにより、プロトコルに定義されているプロパティやメソッドを拡張で必ず追加させることができる。

なお、通常のプロトコルの適用と同じように、複数のプロトコルを指定する場合はカンマ区切りで列挙する。

 

拡張は、クラスだけでなくプロトコルも拡張することができる。

プロトコルはクラスに追加すべきプロパティやメソッドの宣言のみ行い、実際の値や処理は記述できないイメージがあるが、何と、プロトコルの拡張ではメソッドの実装が書けるのである。というか、通常のプロトコルのようなプロパティやメソッドの宣言はできず、メソッドの実装のみできる。

これを利用すれば、プロトコルを適用した全クラスに共通したメソッドを持たせることができる。筆者は、これが拡張の嬉しいところと思っている。

 

データ型を拡張

拡張できるのは、自作したクラスだけでは無い。何と、Swiftに標準で備わっているクラスやデータ型をも拡張することができるのだ。

以下のコードはInt型を拡張して、数字を逆順にするメソッドを追加した例。新しく必要になった変数の値の加工処理を、変数のメソッドを追加するかたちで行えるとは新しい感覚だ。