【Swift】プロトコル(protocol)の使い方

Advent Calendar 2021, iOS, Swift

この記事は最終更新日から1年以上が経過しています。

この記事はレコチョク Advent Calendar 2021の18日目の記事となります。

自己紹介

はじめまして、iOSアプリの開発をしている新卒1年目の深山です!
邦ロック・ジャニーズ・ボカロが大好きで、たくさんのアーティストの情報を追うのに必死な毎日です!

そんな私が、10月に配属されてから2ヶ月の間でiOSアプリの開発に触れて学んだプロトコルについてまとめたいと思います。


1. はじめに

Swiftには他言語でいうインタフェースに似た、プロトコル(protocol)という機能があります。

この記事では、

  • プロトコルとは
  • プロトコルの使用例
  • プロパティ
  • エクステンションの使い方

といった内容について解説していきます。

2. プロトコルとは

Swiftのプロトコルとは、クラスや構造体が保持するプロパティやメソッドなどの決まり事を定めるものです。
プロトコルを定義することによって、複数の型で共通の機能を実装することができます。

型宣言の時にプロトコルに従い、定められた機能を実装することをプロトコルに「準拠する」と言います。

3. プロトコルの使用例

プロトコルには、具体的な処理内容は書きません。
プロトコルに準拠しているクラスや構造体は、プロトコルに定義されているプロパティとメソッドなどを必ず実装しなければなりません。

プロトコルは、 protocolキーワードで定義することができます。
次の例ではプロトコル ArtistProtocolを定義しています。この ArtistProtocolは制約として play()の実装を要求します。

型が ArtistProtocolに準拠するには、 ArtistProtocolが要求しているメソッド play()を実装しなければなりません。

以下は、構造体をプロトコルに準拠させる例です。
型名: プロトコルでプロトコルを記述します。

上記の2つの型 SingerGuitaristは、 ArtistProtocolに準拠していると言えます。
この記述により、 SingerGuitaristは共通のメソッド play()を実装する制約を文法レベルで担保することができます。

そして、 play()を実装しないと、プロトコルの要求を満たしていないとして、コンパイルエラーになります。

ここまでを次のコードで実行してみましょう。

すると以下の結果が出力されます。

Singer型のインスタンスである singerは、 play()を呼び出すことで、 Singer内の play()で定義されているように、 美声を披露と出力します。

また、 Guitarist型のインスタンスである guitaristは、 play()を呼び出すことで、 Guitar内の play()で定義されているように、 ギターソロを出力します。

同じ play()を呼び出しても、それぞれの型で実装した内容が実行される仕組みとなっています。

また、1つの型は複数のプロトコルに準拠することができます。
複数のプロトコルを準拠するには、次のように、カンマ区切りで宣言することができます。

4. プロパティ

プロトコルは、制約として読み取り・書き込みのできるプロパティを定義することができます。

プロパティを定義するには、プロパティ名の型の横に、 { get set }または { get }を記述します。

プロパティの値を取得する際に getメソッドが呼ばれ、プロパティに値を代入する際に setメソッドが呼ばれます。
setメソッドのみの定義はできません。

次の例では、 ArtistProtocolgetメソッドを定義し、 AgeProtocolgetメソッドと setメソッドを定義しています。

次のコードを実行してみましょう。

すると以下の結果が出力されます。

また、 singerageの値に30を代入し、同じようにprint文で出力してみましょう。

すると以下の結果が出力され、 ageの値が更新されたことが確認できます。

5. エクステンションの使い方

プロトコルを使うにあたって、エクステンション(extension)には次の2つの役割があります。

  1. プロトコルの準拠
  2. プロトコルの拡張

これらついて詳しく紹介していきます。

5-1. プロトコルの準拠

3.の後半で、複数のプロトコルの準拠はカンマ区切りでできることを紹介しました。

しかし、カンマ区切りで複数のプロトコルを記述すると、どのプロパティやメソッドが、どのプロトコルに準拠させているかわかりづらいという点があります。

そこで、エクステンションを使ってプロトコルを準拠させてみましょう。
エクステンションを使うと、プロトコルを1つずつ準拠できるので、可読性があがるというメリットがあります。
次の例では、2つのプロトコルをそれぞれエクステンションを使って準拠させています。

カンマ区切りで定義するよりも明確にプロトコルが区別されているのがわかります。

5-2. プロトコルの拡張

プロトコルは、エクステンションを使って拡張させることができます。
これはインターフェースを拡張するのではなく、実装の処理を追加するのに使われ、メソッドのデフォルト実装を持つことができます。

次の例では、 ArtistProtocolにメソッドを追加しています。
準拠先では、追加されたメソッドを実行することができます。

次のコードを実行してみましょう。
say()はプロトコルに実装済みなので実行することができます。

すると以下の結果が出力されます。

また、下記のように protocol内にも say()を定義することで、任意の型の say()に異なる処理を入れたいときにも対応できるようになります。

次のコードを実行してみましょう。

すると以下の結果が出力されます。


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

明日のレコチョク Advent Calendar 2021は19日目「Androidアプリ開発2ヶ月弱の新卒が思う、初学者でも参考になったサイト8選」です。お楽しみに!

参考