[Swift] Type type ~ Enumeration type ~

What is an enumeration type?

The enumeration method is a type of value type, which is a type that groups multiple identifiers together.

Taking the day of the week as an example, there are seven types, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday and Sunday. ** In enumeration type, these 7 identifiers can be treated as one type. ** **

Each identifier of an enumeration type is called a case.

Also, so that it cannot be Thursday at the same time as Tuesday, ** Cases are exclusive. ** **

Even in the standard library, some types are treated as enumerated types. For example, the Optional \ type is an enumeration type that appears frequently.

Definition method

Enums are defined using the enum keyword and the case keyword.


enum enum name{
case Case name 1
case Case name 2
・ ・ ・
Definition of other enums
}

Enum instantiation is a bit different from structs and classes, Instantiate by specifying the case name, such as enum.name.casename.

The following sample code defines each day of the week in the enum Weekday and I'm instantiating .monday and .friday.


enum Weekday {
    case sunday
    case monday
    case tuesday
    case wednesday
    case thursday
    case friday
    case saturdar
}

let monday = Weekday.monday
let friday = Weekday.friday

Enums can also define initializers. Add an initializer and assign each case according to the string passed as an argument.


enum Weekday {
    case sunday
    case monday
    case tuesday
    case wednesday
    case thursday
    case friday
    case saturdar
    
    init?(japanese: String) {
        switch japanese {
        case "Day": self = .sunday
        case "Moon": self = .monday
        case "fire": self = .tuesday
        case "water": self = .wednesday
        case "wood": self = .thursday
        case "Money": self = .friday
        case "soil": self = .saturdar
        default: return nil
        }
    }
}

let sunday = Weekday(japanese: "Day")   // Optional<Weekday.sunday>
let monday = Weekday(japanese: "Moon")   // Optional<Weekday.monday>

Enums can have methods and properties in addition to the initializer, Properties are limited and cannot have ** stored properties. ** **

** That is, enums can only have compute properties. ** **

raw value

The enumeration type can be set to the value corresponding to each case. This value is called the raw value.

All rawValue types must be the same, The types that can be specified are ** Int type, Double type, String type, Character type **, and so on.

How to define rawValue Like when defining a superclass in a class enum enum name: Defined as rawValue type {}


enum enum name:type of rawValue{
case Case name 1= rawValue1
case Case name 2= rawValue2
}

The enumeration type with the rawValue of Int type set is as follows.


enum Sample: Int {
    case a = 1
    case b = 2
    case c = 3
}

For enums that have rawValue defined Implicitly added functionality for converting between rawValue and enums.

The added features are the failable initializer init (rawValue :) and There are two properties, rawValue.

The failable initializer takes a value of the same type as rawValue as an argument.

** If there is a case with matching rawValue, return the corresponding case and Returns nil if no case matches rawValue. ** **

Also, to get the rawValue corresponding to the case, Access the rawValue property implicitly declared with the variable name .rawValue.


enum Sample: Int {
    case a = 1
    case b = 2
    case c = 3
}

let a = Sample(rawValue: 1)   // a
let d = Sample(rawValue: 4)   // nil
print(a?.rawValue)

Execution result
Optional(1)

Default value of rawValue

There is a default value for rawValue of Int type and String type, If you do not specify a value, the default value is applied.

The default value of rawValue of Int type is ** The first case is 0 and the value is incremented thereafter. ** **

The default value of rawValue of String type is ** The default value is the case name as it is. ** **

Since the rawValue is set to 100 with case other = 100, After that, the default value will be 100 + 1.


//Int type rawValue
enum SampleInt: Int {
    case none
    case one
    case other = 100
    case otherPlusOne
}

SampleInt.none.rawValue   // 0
SampleInt.one.rawValue   // 1
SampleInt.other.rawValue   // 100
SampleInt.otherPlusOne.rawValue   // 101

//String type rawValue
enum SampleString: String {
    case home
    case shcool
    case park
}

SampleString.home.rawValue   // home
SampleString.shcool.rawValue   // shcool
SampleString.park.rawValue   // park

Associative value

Enumerated instances, in addition to case information You can add additional information called ** associative value **.

There is no limit to the types that can be specified for associative values.

RGB (Red, Green, Blue) exists as a typical numerical expression of color.

Like the following sample code ** If the expression method (rgb) is expressed as a case and the numerical value (each value of rgb) is expressed as an associative value **, RGB can be represented as an enumeration.

Like RGB, all associative value types can be the same type, Different types such as String, Int, String as in case human are okay.

We have defined an enum Associated, and we have defined two cases in it.

After that, instantiate with constant color and constant human, Each instance is stored in an array array that stores the Associated type.

The values ​​in the array are fetched in order with the for statement, and conditional branching is performed with the switch statement. At this time, as a method for extracting the associative value from the enumeration type, I am using the ** value binding pattern **.


enum Associated {
    case rgb(Float, Float, Float)
    case human(String, Int, String)
}

let color = Associated.rgb(0.0, 0.33, 0.66)
let human = Associated.human("Saitou", 20, "fishing")

let array: [Associated] = [color, human]

for item in array {
    switch item {
    case .rgb(let r, let g, let b):
        print("Red: \(r), Green: \(g), Blue: \(b)")
    case .human(let name, let age, let hobby):
        print("name: \(name),age: \(age),hobby: \(hobby)")
    }
}

Execution result
Red: 0.0, Green: 0.33, Blue: 0.66
name: Saitou,age: 20,hobby:fishing

The value binding pattern is a method of assigning a value to a variable or a constant. Specifically, it refers to the part of case .rgb (let r, let g, let b).

What kind of processing is let r = 1st argument, let g = 2nd argument, let b = 3rd argument. So, after case, you can use constant r, constant g, and constant b.

Caselterable protocol

If you are using an enum, you may want to get all the cases as an array.

For example, when expressing prefectures as an enumeration type, You will need an array of all cases to see the choices.

The CaseIterable protocol is a protocol that meets that requirement.

** Enumerations that comply with the CaseIterable protocol The allCases property is automatically added. ** **

This allCases property is the property that returns all cases.

In the following sample code I defined enumerated Japan and wrote some prefectures.

After that, when I ran Japan.all Cases, I was able to get all the cases.

The allCases property is in the enum Japan: CaseIterable {} part Since we have declared compliance with CaseIterable, it is automatically created by the compiler.


enum Japan: CaseIterable {
case Gunma,Tochigi,Tokyo,Kanagawa
case Aomori,Iwate,Miyagi,Akita
}

Japan.allCases   // [Gunma,Tochigi,Tokyo,Kanagawa,Aomori,Iwate,Miyagi,Akita]

allCases does not use the compiler-generated implementation You can also implement allCases yourself.

Conditions under which allCases are not automatically generated

If the enum has associative values, allCases will not be automatically generated.

In other words, if you want to enumerate all cases with an enum with associative values, ** Programmers must implement the allCases property themselves. ** **


enum Japan: CaseIterable {
case tokyo(String, String, String, String)
case Kanagawa(String, String, String, String)
    
    static var allCases: [Japan] {
        return [
            .Tokyo("Shinjuku", "Shibuya", "Nakameguro", "Edo River"),
            .Kanagawa("Yokohama", "Kamakura", "Odawara", "Enoshima")
        ]
    }
}

Japan.allCases   // {Tokyo"Shinjuku", "Shibuya", "Nakameguro", "Edo River"}, {Kanagawa"Yokohama", "Kamakura", "Odawara", "Enoshima"}

To access each element, use the value binding pattern mentioned earlier.


enum Japan: CaseIterable {
case tokyo(String, String, String, String)
case Kanagawa(String, String, String, String)
    
    static var allCases: [Japan] {
        return [
            .Tokyo("Shinjuku", "Shibuya", "Nakameguro", "Edo River"),
            .Kanagawa("Yokohama", "Kamakura", "Odawara", "Enoshima")
        ]
    }
}

let japan = Japan.allCases

for item in japan {
    switch item {
    case .Tokyo(let a, let b, let c, let d):
        print("Tokyo:\(a),\(b),\(c),\(d)")
    case .Kanagawa(let a, let b, let c, let d):
        print("Kanagawa:\(a),\(b),\(c),\(d)")
    }
}

Execution result
Tokyo: Shinjuku,Shibuya,Nakameguro,Edo River
Kanagawa: Yokohama,Kamakura,Odawara,Enoshima

That's all for the explanation of enums.

I introduced three types, structs, classes, and enums. Use this type in any situation! To be honest, I still don't understand.

Personally, when defining a type with information that has already been decided, an enumeration type Other than that, basically the structure is used, Should I use a class when I want to use a function that has a reference type or inheritance? It is an impression.

I would like to share this again when I become more full-fledged.

In addition to this article, there is an article that describes the types of types, so please have a look!

[Swift] Type type ~ Basic knowledge ~[Swift] Type type ~ Structure ~[Swift] Type Type-Class Part 1-

Thank you for watching until the end.

Recommended Posts

[Swift] Type type ~ Enumeration type ~
[Swift] Shared enumeration type
Enum (enumeration type)
[Java] Enumeration type
[Swift] Type type ~ Structure ~
[Swift] Type components ~ Type nesting ~
[Swift] Type component ~ Subscript ~
[Swift] Type design guidelines
[Swift] Type component ~ Initializer ~
[Swift] About enumeration types
[Swift] Type type-Class sequel-
[Swift] Type component ~ Method ~
[Swift] Summary about Bool type
[Swift] Type type-Class first part-
[Swift] Type component ~ Property Part 2 ~
Great Swift pointer type commentary
[Java] Express Enum type without using Enum (enumeration) type
[Swift] Converts a UInt64 type integer to [UInt8]
Pass type
[Swift] Closure
Directory type
[Practice] Enumeration
Try to sort classes by enumeration type
Human type
[Swift / For beginners] Write smartly with type inference
[Swift] Perform error handling with Optional <Wrapped> type