Swiftのプロトコル分割と合成を徹底解説!小さく作って大きく組む実践方法
生徒
「先生、Swiftでプロトコルを使っているんですが、だんだんルールが大きくなって複雑になってきました。もっと整理する方法はありますか?」
先生
「とてもいい質問だね。実はSwiftにはプロトコルを分割したり、逆に組み合わせて使う方法があるんだよ。それを『プロトコル分割』と『プロトコル合成』と呼ぶんだ。」
生徒
「プロトコル分割と合成? どういう意味ですか?」
先生
「簡単にいうと、大きなルールを小さく分けて管理しやすくし、それを必要に応じて組み合わせて使うという考え方だよ。日常生活での例えも交えて説明していこう。」
1. プロトコル分割とは?
プロトコル分割とは、1つの大きなプロトコルを複数の小さなプロトコルに分けることです。なぜ分けるのかというと、1つのプロトコルにあれもこれも詰め込みすぎると「重いルールブック」になってしまい、使いにくくなるからです。
例えば、「動物」というプロトコルを作るときに「走る」「鳴く」「泳ぐ」「飛ぶ」など全部入れてしまうと、犬や鳥や魚すべてに余計な機能を実装する羽目になります。そこで、機能ごとに小さく分割するのです。
protocol Runnable {
func run()
}
protocol Barkable {
func bark()
}
protocol Flyable {
func fly()
}
このように分けることで、「犬は走ると鳴く」「鳥は飛ぶと鳴く」といった形で柔軟に組み合わせられるようになります。
2. プロトコル合成とは?
プロトコル合成とは、複数の小さなプロトコルを組み合わせて「大きなルール」を作ることです。これにより、小さく分けたルールを状況に応じてまとめて使えるようになります。
struct Dog: Runnable, Barkable {
func run() {
print("犬が走ります")
}
func bark() {
print("ワンワン!")
}
}
struct Bird: Flyable, Barkable {
func fly() {
print("鳥が飛びます")
}
func bark() {
print("チュンチュン!")
}
}
犬が走ります
ワンワン!
鳥が飛びます
チュンチュン!
このように必要な機能だけを組み合わせることで、シンプルかつ効率的に設計できます。
3. プロトコル合成を型として利用する
Swiftでは、プロトコルを「型」として扱えます。そして&記号を使って複数のプロトコルをまとめることができます。これがプロトコル合成の大きな特徴です。
func play(with animal: Runnable & Barkable) {
animal.run()
animal.bark()
}
let dog = Dog()
play(with: dog)
犬が走ります
ワンワン!
このように引数に「走れて鳴ける動物」という条件を指定できます。条件を満たす型だけが使えるため、コードの安全性が高まります。
4. 現実世界の例えで理解しよう
例えば、学校の部活動を考えてみましょう。「運動部」という大きなカテゴリを作ると、中にはサッカー部、野球部、陸上部などが含まれます。それぞれに「走る」「投げる」「蹴る」などの動作が必要になります。もし大きなルールに全部まとめると、陸上部に「バットで打つ」というルールまで入ってしまうことになります。
しかし、ルールを小さく分けて「走るプロトコル」「投げるプロトコル」「蹴るプロトコル」として定義すれば、サッカー部は「走る+蹴る」、野球部は「走る+投げる」と組み合わせて表現できます。これがプロトコル分割と合成のイメージです。
5. プロトコル分割と合成のメリット
プロトコル分割と合成を使うことで得られるメリットはたくさんあります。
- コードの再利用性が高まる
- 余計な実装を強制されないのでシンプル
- 必要に応じて組み合わせる柔軟性がある
- 読みやすく保守しやすい設計ができる
特に、アプリが大きくなるにつれて役割を細かく分けたい場面が多く出てきます。そのときにプロトコル分割と合成を使えると、開発がとても楽になります。
6. 初心者が意識すべきポイント
初心者の方が最初にプロトコルを学ぶときは「ルールを一つにまとめてしまいがち」です。しかし、小さく分けることで後々のコードがすっきりすることを意識してみましょう。そして、必要に応じて合成すればよいのです。
最初から完璧に分割する必要はありません。小さなアプリでも試しに「走る」「飛ぶ」「鳴く」といった小さなプロトコルを作ってみると、Swiftの柔軟さが理解しやすくなります。