[Swift] Enumerations

East Silver·2021년 12월 28일
0

애플 공식 문서를 바탕으로 정리합니다!

Enumerations

An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.

Enumerations in Swift are first-class types in their own right.

Enumeration Syntax

enum SomeEnumeration {
    // enumeration definition goes here
}

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

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

Each enumeration definition defines a new type.

var directionToHead = CompassPoint.west
directionToHead = .east

Matching Enumeration Values with a Switch Statement

You can match individual enumeration values with a switch statement.
When it isn’t appropriate to provide a case for every enumeration case, you can provide a default case to cover any cases that aren’t addressed explicitly

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")
default:
    print("??")
}
// Prints "Watch out for penguins"

Iterating over Enumeration Cases

For some enumerations, it’s useful to have a collection of all of that enumeration’s cases. You enable this by writing : CaseIterable after the enumeration’s name. Swift exposes a collection of all the cases as an allCases property of the enumeration type
사용 이유: 코드의 가독성과 안전성

enum Beverage: CaseIterable {
    case coffee, tea, juice
}

let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"

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

Associated Values (원시값)

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
//create new barcodes using either type:
var productBarcode = Barcode.upc(8, 85909, 51226, 3)

//assign the same product a different type of barcode:
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

At this point, the original Barcode.upc and its integer values are replaced by the new Barcode.qrCode and its string value. Constants and variables of type Barcode can store either a .upc or a .qrCode (together with their associated values), but they can store only one of them at any given time.

Enumeration Case Pattern(+ 좀 더 찾아보기)

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

If all of the associated values for an enumeration case are extracted as constants, or if all are extracted as variables, you can place a single var or let annotation before the case name

switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
    print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
    print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."

https://boidevelop.tistory.com/22

원시값의 한계

  • 모든 케이스가 동일한 형식을 사용해야함
  • 케이스당 값을 하나밖에 저장할 수 없음
  • 원시값 문자열에 숫자가 포함되어 있을 경우 숫자만 사용하려면 따로 추출해야하는 번거로움이 있음

Raw Values

enumeration cases can come prepopulated with default values (called raw values), which are all of the same type.

enum TypeName: RawValueType {
	case caseName = Value
}
  • 선언 이후에는 바꿀 수 없습니다!
  • string은 값을 선언하지 않았다면, 이름이 값이 된다
  • character는 선언을 꼭 해줘야한다

Implicitly Assigned Raw Values

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

Implicitly Assigned Raw Values

When we don't assign a raw value for each case, Swift automatically assigns the values for you.
If the first case doesn’t have a value set, its value is 0.

enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}

In the example above, Planet.mercury has an explicit raw value of 1, Planet.venus has an implicit raw value of 2, and so on.

Initializing from a Raw Value

열거형의 새로운 인스턴스를 생성할 때 변수나 상수에 rawValue라는 매개변수로 초기화할 수 있는데 이렇게 되면 반환값으로 해당 Raw Value가 존재하면 해당 케이스의 값이 나오고 존재하지 않는 Raw Value라면 nil이 반환됩니다. 즉 옵셔널 타입으로 반환이 된다

let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus

If you try to find a planet with a position of 11, the optional Planet value returned by the raw value initializer will be nil

let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
    switch somePlanet {
    case .earth:
        print("Mostly harmless")
    default:
        print("Not a safe place for humans")
    }
} else {
    print("There isn't a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"

Recursive Enumerations

Recursive Enumerations는 재귀 열거형으로 어떤 열거형의 케이스에 Associated value의 타입으로 자신의 열거형 타입이 들어간 경우를 말합니다. 이렇게 자신의 열거형 타입을 사용하게 되면 해당 케이스 앞에 indirect라는 키워드를 사용해야 하는데 예를 보면 다음과 같습니다.

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

You can also write indirect before the beginning of the enumeration to enable indirection for all of the enumeration’s cases that have an associated value:

indirect enum ArithmeticExpression {
    case number(Int)
    case addition(ArithmeticExpression, ArithmeticExpression)
    case multiplication(ArithmeticExpression, ArithmeticExpression)
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

A recursive function is a straightforward way to work with data that has a recursive structure. For example, here’s a function that evaluates an arithmetic expression

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

print(evaluate(product))
// Prints "18"
profile
IOS programmer가 되고 싶다

0개의 댓글