見出し画像

列挙型と構造体【Swiftイントロダクション#5】

列挙型

列挙型はenumを使って定義します。また、列挙型はメソッドを持つことができます。

//Int型の列挙型
enum Rank: Int {
   //最初の値を指定
   case ace = 1
   case two, three, four, five, six, seven, eight, nine, ten
   case jack, queen, king
   func simpleDescription() -> String {
       switch self {
       case .ace:
           return "ace"
       case .jack:
           return "jack"
       case .queen:
           return "queen"
       case .king:
           return "king"
       default:
           return String(self.rawValue)
       }
   }
}
let ace = Rank.ace
let aceRawValue = ace.rawValue

画像1

上の例ではデータタイプがIntの列挙型が宣言されています。データタイプがIntなので始めの値を指定すれば残りは値が割り当てられます。上記のコードでは明示的にaceの値が1としていされているので、1 から連番で値が割り当てられます。明示的に数を指定しない場合は、デフォルト値である0から順番に値が割り当てられます。

列挙型の値を取り出す場合は、rawValueプロパティーを使います。上の例では、rawValueを使ってaceの値を取り出しています。

init?(rawValue:)を使って、列挙型のインスタンスをデータから作ることができます。

if let convertedRank = Rank(rawValue: 3) {
   let threeDescription = convertedRank.simpleDescription()
}

また、列挙型はメソッドを持つことができます。例えばこのRankというenumはsimpleDescription()というメソッドを持っています。このメソッドは、rawValueが1の場合はaceを、11の場合はjackを、12の場合はqueenを、13の場合はkingを返します。

rawValueを12として、インスタンスを生成し、simpleDesctiption()を呼び結果をプリントしてみます。

rawValueに12を入れてRankという列挙型のインスタンスを生成した場合、simpleDesctiption()では上述の通り12がqueenと一致するのでswitch文のところで"queen"が返されます。そのため、threeDescriptionにはqueenが入るので結果としてqueenがプリントされます。

画像2

また、3を入れてインスタンスを生成した場合には、3はcaseに対応する値がないので、switch caseの中のデフォルトが実行され、rawValueでセットされた値が文字列としてそのままプリントされます。

画像3

列挙におけるCaseの値

列挙におけるcaseの値は、ただcaseに割り当てられている値を返すのではなく、意味のある値が入ります。もし値が不要の場合には、caseの値の記述を省略します。

enum Suit {
   case spades, hearts, diamonds, clubs
   func simpleDescription() -> String {
     //このselfはSuitを指している
       switch self {
       case .spades:
           return "spades"
       case .hearts:
           return "hearts"
       case .diamonds:
           return "diamonds"
       case .clubs:
           return "clubs"
       }
   }
}
//heartsの型が明示されていないのでSuitをつける
let hearts = Suit.hearts
let heartsDescription = hearts.simpleDescription()

上記の例で、heartsケースが参照される方法が2つあることに注意してください。定数のheartsに値を代入する場合は、heartsの型が明示されていないので、Suit.heartsのようにフルネームが使われています。 一方switch文の中では、短縮系の.heartsが使われています。短縮系が使われている理由は、selfがもう既にsuitを指していることが分かっているからです。

もしケースに値を割り当てたい場合、2つの方法があります。
一つ目は列挙型の宣言時に値を割り当てる方法です。この場合はケースは毎回同じ値を返します。
もう一つの方法は、列挙型のインスタンスを作る時に、それぞれのケースに関連する値を割り当てる方法です。この方法では、ケースのインスタンスごとに値を変えることができます。
下の例では、サーバーに日の出と日の入りの時間をリクエストしています。サーバーは通信が成功した場合には、リクエストされた情報(下の例だと日の出・日の入り時間)を返します。失敗した場合にはエラーメッセージを返します。

enum ServerResponse {
   case result(String, String)
   case failure(String)
}
let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")
//resultが実行される
switch success {
case let .result(sunrise, sunset):
   print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
   print("Failure...  \(message)")
}

画像4

構造体

構造体はstructを使って定義します。構造体は関数や初期化などクラスと同じような機能を持っています。最も重要な違いの一つは、変数に入れられるときクラスは参照が渡されますが、構造体は常にコピーが渡されるという点です。

struct Card {
   var rank: Rank
   var suit: Suit
   func simpleDescription() -> String {
       return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
   }
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

画像5

次回は【プロトコルとエクステンション】について解説します!

今までのSwiftイントロダクション
#1 シンプルな値
#2 制御フロー
#3 関数とクロージャ
#4オブジェクトとクラス

いいなと思ったら応援しよう!