見出し画像

Swiftでプログラミング。 - Enumerations 1

列挙型(Enum)は、関連する値をグループにして共通の型を定義し、コード内で型に安全な方法でそれらの値を操作できるようにします。

"C"言語では、C列挙型が関連する名前を整数値のセットに割り当てています。 Swiftの列挙型ははるかに柔軟性があり、列挙の各ケースに値を提供する必要はありません。列挙型ごとに値(Raw Valueと呼ばれる)が提供されている場合、値は文字列、文字、または任意の整数型または浮動小数点型の値にすることができます。

あるいは、列挙型は、ユニオンやバリアントが他の言語で行うのと同じように、それぞれの異なるケース値とともに格納される任意のタイプの関連値を指定できます。関連するケースの共通セットを1つの列挙の一部として定義できます。各列挙には、適切なタイプの異なる値のセットが関連付けられています。

Swiftの列挙は、それ自体がファーストクラスの型です。これらは、列挙型の現在の値に関する追加情報を提供する計算プロパティや、列挙型が表す値に関連する機能を提供するインスタンスメソッドなど、従来はクラスでのみサポートされていた多くの機能を採用しています。列挙型は、初期ケース値を提供するイニシャライザーを定義することもできます。元の実装を超えて機能を拡張するように拡張できます。また、プロトコルに準拠して標準機能を提供できます。

Enumeration Syntax  基本の形

enumキーワードを使用して列挙型を導入し、それらの定義全体を中括弧のペア内に配置します。

    enum SomeEnumeration {
       // enumeration definition goes here
   }

コンパスの4つの主要なポイントの例を次に示します。

    enum CompassPoint {
       case north
       case south
       case east
       case west
   }

列挙型で定義された値(北、南、東、西など)は、その列挙型のケースです。 caseキーワードを使用して、新しい列挙ケースを導入します。

CやObjective-Cなどの言語とは異なり、Swift列挙型のケースにはデフォルトで整数値が設定されていません。 上記のCompassPointの例では、北、南、東、西は暗黙的に0、1、2、3に等しくありません。代わりに、異なる列挙ケースは、明示的に定義されたタイプのCompassPointを使用したそれ自体の値です。

複数のケースをコンマで区切って1行に表示できます。

    enum Planet {
       case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
   }

各列挙定義は、新しいタイプを定義します。 Swiftの他のタイプと同様に、それらの名前(CompassPointやPlanetなど)は大文字で始まります。 列挙型に複数の名前ではなく単数の名前を付けて、自明であると読み取れるようにします。

var directionToHead = CompassPoint.west

directionToHeadのタイプは、CompassPointの可能な値の1つで初期化されたときに推測されます。 directionToHeadがCompassPointとして宣言されたら、短いドット構文を使用して別のCompassPoint値に設定できます。

directionToHead = .east

directionToHeadのタイプはすでにわかっているため、値を設定するときにタイプを削除できます。 これにより、明示的に型指定された列挙値を操作するときに、非常に読みやすいコードが作成されます。

Matching Enumeration Values with a Switch Statement  列挙値とSwitchステートメントの照合

個々の列挙値をswitchステートメントと照合できます。

   directionToHead = .south
   
   switch directionToHead {
   case .north:
       print("Lots of planets have a north")
   case .south:
       print("Watch out for penguins")
   case .east:
       print("Where the sun rises")
   case .west:
       print("Where the skies are blue")
   }
   // Prints "Watch out for penguins"

このコードは次のように読むことができます。

「directionToHeadの値を考えましょう。 .northに等しい場合は、「多くの惑星に北があります」と出力されます。 .southに等しい場合は、「ペンギンに気をつけて」と出力されます。

列挙型のcaseを使うときは、switchを使う必要があります。もし .westの場caseが省略された場合は、CompassPointの全てのcaseが定義されていないため、このコードはコンパイルされません。 定義した列挙型を全て要求することで、列挙型のcaseが誤って省略されないようにします。

すべての列挙のcaseにあてはまらない場合は、デフォルトのcaseを用意しておきます。

   let somePlanet = Planet.earth
   
   switch somePlanet {
   case .earth:
       print("Mostly harmless")
   default:
       print("Not a safe place for humans")
   }
   // Prints "Mostly harmless"

Iterating over Enumeration Cases   列挙型の繰り返し

一部の列挙では、その列挙のすべてのcaseをコレクション(配列)として使えれば便利です。 これを有効にするには、列挙型の名前の後に:CaseIterableに適応させます。 そうすることでcaseをコレクションとして列挙型のallCasesプロパティを持つようになります。 次に例を示します。

   enum Beverage: CaseIterable {
       case coffee, tea, juice
   }
   let numberOfChoices = Beverage.allCases.count
   print("\(numberOfChoices) beverages available")
   // Prints "3 beverages available"

上記の例では、Beverage.allCasesを記述して、Beverage列挙のすべてのケースを含むコレクションにアクセスします。 allCasesは、他のコレクションと同じように使用できます。コレクションの要素は列挙型のインスタンスであるため、この場合は飲み物の名前です。 上記の例では、caseの数をカウントし、以下の例では、forループを使用してすべてのケースを繰り返し処理しています。

    for beverage in Beverage.allCases {
       print(beverage)
   }
   // coffee
   // tea
   // juice

上記の例で使用されている構文は、CaseIterableプロトコルに準拠させて使います。 以下公式のリファレンスです。


この記事が気に入ったらサポートをしてみませんか?