enumについて

enum と構造体の違い

Swiftにおける enum(列挙型)と struct(構造体)の主な違いは、表現したいデータの性質にあります。どちらもメソッドやプロパティを持つことができる値型ですが、用途が異なります。 

主な違い

比較項目 enum(列挙型)struct(構造体)
意味・用途限定された「選択肢」や「状態」を表す。複数の「データ(プロパティ)のまとまり」を表す。
表現方法複数のcase(ケース)のいずれか1つである状態を表現する。複数の異なるデータを同時に保持する構造を表現する。
インスタンス化特定のケースとしてのみ存在する。データを持った具体的なインスタンスとして生成される。
関連値各ケースに異なる型の関連値(Associated Values)を持たせることができる。独自のプロパティ(stored properties)を持つ。
データの持ち方定義されたケースのどれか一つになる複数の値を同時に保持する
主な役割「種類や状態」を表現する「もの(Entity)」を表現する
得意なこと条件分岐(switch 文との相性が抜群)複雑な属性を持つデータの管理
拡張性associated value でケースごとに異なるデータを持たせるプロパティを増やして情報をリッチにする

詳細な説明

enum(列挙型)

enumは、取りうる値が固定されていて、そのうちの1つだけを選択的に表現したい場合に使用します。 

  • : 信号機の色 ()、ユーザーの状態 (ログイン中ログアウト中)、曜日など。
  • 各ケースに異なるデータを付加できる「関連値」の機能が強力で、例えばエラーの種類とそれに付随する詳細情報を一緒に表現するのに適しています。

struct(構造体)

structは、複数の異なるプロパティを組み合わせて一つのまとまったデータ構造を表現したい場合に使用します。 

  • : ユーザー情報 (名前年齢住所)、座標 (xy)、商品の詳細情報など。
  • データそのものをモデル化し、そのデータの塊に対して振る舞い(メソッド)を追加するのに適しています。

使い分けの判断基準

迷ったときは、以下の質問を自分に投げかけてみてください。

「それは『属性のリスト』ですか?」

  • Yes → struct

「それは『限られた選択肢』ですか?」

  • Yes → enum

まとめ

どちらも値型であり、メソッドを定義できるなど共通点も多いですが、**「閉じた選択肢の集合」を扱いたい場合はenum「複数のプロパティで構成されるデータの塊」**を扱いたい場合はstructを選ぶのが基本的な使い分けとなります。 

none

enum(列挙型)で「値がない」状態や「なし」を表すケースを定義する方法は、主に以下の2通りです。

1. 単純なケースとして定義する

最も一般的な方法は、none という名前のケースを明示的に作成することです。

2. Optional型(nil)を利用する 

Swift標準のOptional型は、内部的に case none を持つ enum です。独自の enum に none を作らず、「値そのものがない可能性」を Optional で表現するのがSwiftらしい設計です。

注意点:Optional.none との名前衝突

自分自身で case none を定義すると、Optional型の .none(つまり nil)と名前が衝突し、コンパイラが混乱することがあります。

解決策・推奨される命名:

  • none 以外の名前を使う: case emptycase undefinedcase unknown など。
  • Optionalを使う: そもそも case none を作らず MyEnum? 型として扱う。
  • 明示的に指定する: Optional.none または MyEnum.none と記述する。

フィルタリング

SwiftUIのForEachで特定のケース(emptyなど)を除外してViewを生成するには、主に「フィルタリングした配列を渡す」「ループ内で条件分岐する」かの2通りの書き方があります。 

1. 配列をフィルタリングして渡す(推奨)

ForEachに渡す前に .filter を使って特定のケースを除外します。Viewのコードがスッキリし、不要な計算も抑えられるため、こちらの方法が推奨されます。 

2. ループ内で if 分岐する

ForEach のクロージャ内で条件判定を行い、表示したくないケースのときに何も返さない(あるいは EmptyView() を返す)方法です。

どちらを使うべきか?

  • 基本は「1. フィルタリング」ForEach に渡すデータそのものを絞り込む方が、SwiftUIの描画効率やコードの可読性の面で優れています。
  • 計算プロパティに切り出す:フィルタリング処理をViewの中に直接書くのが長い場合は、以下のように enum や View の計算プロパティとして定義しておくとさらに綺麗になります。

補足

CaseIterable プロトコルを enum に採用することで、 allCases という全ケースの配列が自動生成されるようになります。これを利用することで簡単にフィルタリングが可能です。 

VBA の enum との違い

VBAのEnumとSwiftのenumは、名前は同じですが性質と機能が大きく異なります

VBAのEnumが単なる整数の定数に別名を付けたエイリアス(別名)であるのに対し、Swiftのenumは遥かに強力で、言語の重要な構成要素の一つです。

VBAのEnumの性質

VBAのEnumは、基本的に整数値のグループ化と可読性の向上を目的としています。

Swiftのenumの強力な点

Swiftのenumは、VBAとは異なり、以下のような高度な機能を持っています。

  1. 関連値 (Associated Values):
    各ケースが異なる型のデータを持つことができます。これがVBAにはない最大の機能です。(前の回答のAPIError.networkError(code: Int, message: String)のように)
  2. メソッドとプロパティ:
    structclassと同様に、計算プロパティやインスタンスメソッドを持つことができます。
  3. 値型としての振る舞い:
    structと同様に値型として扱われます。

まとめ

VBAからSwiftへ移行される場合、Swiftのenumは「単なる定数」ではなく、「高度な機能を持つ独自のデータ型」として捉える必要があります。この違いを理解すると、Swiftでのデータモデリングの幅が大きく広がります。

コメント

タイトルとURLをコピーしました