【Swift】Equatableプロトコルとは?使い方や使う目的、活用時の注意点までわかりやすく解説!

Swiftで「この2つの値は同じかどうか」を判定したい場面はとても多いですよね。

そんなときに欠かせないのが Equatableプロトコル です。

Equatableプロトコル を使うことで「2つの値が等しいかどうか」を判定できるようになります。

もしEquatableを使わなかったら、「同じ見た目のインスタンスなのに、等しいと判定できない」 という不便なことが起こりますが、初心者にはめちゃくちゃ理解しにくい、、、

私もアプリ開発始めて1年ぐらいは正直、

「Equatableプロトコルって何のために使うんだろう?エラーになるから入れているけど、、、」

という感じで全く理解できずになんとなく使っていました笑

この記事では、Equatableとは何か、どんな目的で使うのか、そして「使わなかったらどうなるのか?」をなるべくわかりやすくに解説していきます。

Equatableとは?

EquatableはSwift標準のプロトコルで、「2つの値が等しいかどうか」を判定できるようにするための仕組みです。

このプロトコルに準拠すると、== 演算子を使ってオブジェクト同士を比較できるようになります。

たとえば、配列の中に特定の要素が含まれているかを判定する contains や、要素のインデックスを調べる firstIndex(of:) なども、要素が Equatable に準拠していることが前提です。

このEquatableプロトコルを理解するためには、Equatableを使わない場合の具体例で考えるのがおすすめです。

Equatableを使わなかった場合の具体例

以下のような構造体 User を考えてみましょう。

上記コードの use1 と use2 の2つのインスタンスは、見た目はまったく同じですよね?

でも、この状態ではSwiftは「同じユーザーだ」とは判断してくれません。

試しに比較してみようとすると…

これはコンパイルエラーになります。

なぜなら、User が Equatable に準拠していないため、どのプロパティ(今回だとid やname)が同じなら等しいという基準がないからです。

例えば、id が同じなら「2つは等しい」とみなしてよい、とか、 idとname それぞれが一致する場合だけ「2つは等しい」という基準がないとSwiftは2つのインスタンスが等しい可動化の判定ができません。

同じように、配列の中に含まれているかを調べようとしても、Equatableを指定していないとエラーになります。

このように、Equatableがないと「等しいかどうか」を判定する処理そのものが書けないのです。

Equatableを使うとどう変わる?

では、User に Equatable をつけてみましょう。

たったこれだけです。

Swiftは自動で下記のような == の比較方法を合成してくれます(すべてのプロパティがEquatableならOK)。

上記の意味は、「左側のidと右側のidが一致する」、かつ「左側のnameと右側のnameも一致する」であれば、Trueを返す、という意味です。

つまり、Swiftが「2つのインスタンスが等しい」と判断する基準を「idとnameどちらも一致すれば等しい」と設定してあげているのです。

この状態であれば、先ほどのコードはすべて正常に動作します。

つまり、「プロパティが全部同じなら、等しいとみなす」という判断を、Swiftが自動でしてくれるのです。

プロパティの一部だけで比較したい場合

業務アプリなどでは「このIDが同じなら同一とみなす」といったケースもあります。

そんなときは == の定義を自分で書くこともできます。

このようにすれば、IDが同じなら等しい(nameの値が違っていたとしても)とSwiftが判断してくれるようになります。

このカスタマイズができるのもEquatableの大きなメリットです。

Equatableの主な活用場面

Equatableはとにかく様々なところで使われます。

特に多いのが下記のような場面です。

  • 配列の中に特定の要素があるかを確認したいとき(contains)
  • 2つの構造体インスタンスが同じ内容かを判定したいとき(==)
  • SwiftUIの onChange(of:) で状態の変化を検知したいとき
  • SwiftUIの .equatable() で再描画の最適化をしたいとき
  • テストコードで、期待値と実際の値が一致するか確認したいとき

SwiftUIでの具体的な使い方例

SwiftUIでもEquatableは重要な役割を果たします。

例えば、 onChange を使って、値が変わったときに処理を行いたい場合の例です。

ここで nameString(Equatable準拠)なので、前回のname と新しい値が違う場合だけクロージャが呼ばれます。

もしEquatableじゃなかったら、「値が変わったかどうか」が判定できず、このような便利な処理はできません。

Equatableを使うときの注意点

Equatable はとても便利ですが、いくつか知っておかないとつまずきやすいポイントがあります。

特に「どのプロパティを比較対象にするのか」は、アプリの設計に直結する大事な部分です。

1. 自動実装が効くのは「すべてのプロパティが Equatable な場合」だけ

構造体や列挙型のすべてのストアドプロパティが Equatable に準拠していれば、自動で == が生成されます。

逆に、プロパティの中に Equatable でない型(Anyクロージャ など)が含まれている場合は、自分で == を実装する必要があります。

2. class(参照型)では自動実装されない

structenum では便利な自動合成が使えますが、class(参照型)は違います。

クラスは インスタンスの参照そのものが同一かどうか を扱うため、== の比較基準を自分で定義する必要があります。

例:

3. 等しいと判定する基準は用途に応じて設計する

単純に「すべてのプロパティが一致すれば等しい」とするのは便利ですが、必ずしも最適とは限りません。

  • ユーザー管理 → id が同じなら同じユーザーとみなす
  • 商品管理 → productCode が同じなら同じ商品とみなす

まとめ

Equatable は、Swift での開発に欠かせない基本プロトコルのひとつです。

最後にポイントを整理してみましょう。

  • Equatableは、「値が等しいかどうか」を判定するためのプロトコル
  • SwiftUIやテストなど、さまざまな場面で使われる超重要なプロトコル
  • 構造体や列挙体では、プロパティがすべてEquatableなら自動で実装される
  • Equatableがないと ==contains など、等価判定が一切できない
  • 自分で == を定義することで、「どのプロパティが同じなら等しいか」をカスタマイズできる

Swiftでアプリを作るうえで、Equatableをうまく使うことはとても大事なスキルです。

「どんなときに等しいとみなすのか?」という考え方をしっかり身につけていきましょう。

おすすめの記事