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 \
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. ** **
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)
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
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.
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.
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