構造体・クラス・列挙型

構造体

値型の一種。ストアドプロパティの組み合わせで、一つの値を示す。 構造体のプロパティを変更することは、その構造体を別の値にすることであり、変数への再代入が必要である。

struct User {
   let name = "Murata"
   let age = 20
}

定数のストアドプロパティは変更できない。

struct User {
   var name = "Murata"
   var age = 20
}

var user1 = User()
user1.name = "123"
let user2 = User()
user2.name = "345" => コンパイルエラーになる

クラス

参照型のデータ構造。 構造体との違いは、1・参照型であること 2・継承ができること の2つである。

クラスに紐づく要素

クラスプロパティとクラスメソッドがある。スタティックプロパティ・スタティックメソッドとは違い、オーバーライドができる。

class User {
    class var name: String {
        return "bakuro"
    }
    class func printUser() {
        print("this is class method")
    }
}

print(User.name) => bakuro
User.printUser() => this is class method

列挙型

値型の一種で、複数の識別子をまとめる。それぞれのケースは排他的である。

enum Weekday {
    case monday
    case tuesday
    //...
}

let monday = Weekday.monday

一般的にWeekday.mondayのようにケース名を指定してインスタンスを生成する。イニシャライザを持つこともできる。

enum Weekday {
    case monday
    case tuesday
    
    // nilになるかもしれないので失敗可能イニシャライザ
    init?(name: String) {
        switch name {
            case "月": self = .monday
            case "火": self = .tuesday
            // switchは全てを網羅すること
            default: return nil
        }
    }
}

let monday = Weekday(name: "月") // Optional(Main.Weekday.monday)
let tuesday = Weekday(name: "火") // Optional(Main.Weekday.tuesday)
let sunday = Weekday(name: "日") // nil

また、メソッドやコンピューテッドプロパティを持つこともできる。

enum Weekday {
    case monday
    case tuesday
    func isDay() {
        print(true)
    }
    var japaneseName: String {
        switch self {
            case .monday: return "月曜日"
            case .tuesday: return "火曜日"
        }
    }
}

実体の定義

列挙型のケースにはそれぞれ対応する値を設定できる。これをraw valueと呼ぶ。そして全てのケースのraw valueは同じであること。Int, String, Doubleなどを型に指定できる。また、暗黙的に失敗可能イニシャライザが用意され、対応するケースがあれば、そのケースはインスタンスにし、なければnilを返す。

enum 列挙型名 : ローバリューの型 {
 case ケース名1 = ローバリュー1
 case ケース名2 = ローバリュー2 
}

// 例
enum Nation : String {
    case russia = "ロシア"
    case china = "中国"
    case korea = "朝鮮"
}
let n = Nation(rawValue: "ロシア")
print(n)  // Optional(Main.Nation.russia)
// 失敗可能イニシャライザをもつので、「?」がいる。
print(n?.rawValue) // Optional("ロシア")

let u = Nation(rawValue: "イタリア")
// イタリアというローバリューに一致するケースがないので、nilがかえる。
print(u) // nil
print(u?.rawValue) // nil

ローバリューのデフォルト値

Int, Stringではローバリューにデフォルト値があり、値を指定しない場合はデフォルト値が適用される。 Intなら、最初が0で1,2,3...と適用される。 Stringなら、ケース名がそのまま適用される。

enum Number : Int, CaseIterable {
    case zero
    case one
    case two
}

enum Alphabet : String, CaseIterable {
    case a
    case b
    case c
}


print(Number.zero.rawValue) // 0
print(Number.one.rawValue)  // 1


print(Alphabet.a.rawValue) // a
print(Alphabet.b.rawValue) // b

// enumを, CaseIterableに準拠させるとallCasesによって、enumの全てのケースを配列で取得できる。
print(Number.allCases) //[Main.Number.zero, Main.Number.one, Main.Number.two]
print(Alphabet.allCases) // [Main.Alphabet.a, Main.Alphabet.b, Main.Alphabet.c]