Swift/The Swift Programming Language

[Swift] Enumerations(열거형) - 1

Kellang 2023. 5. 30. 21:03

Enumerations

열거형은 연관된 값들을 공통된 타입으로 묶은 그룹이며, 타입 안전(type-safe)하게 사용하게 해준다.

 

스위프트의 열거형은 유연하다. 각 케이스에 값을 할당하지 않아도 되며, 스트링, 캐릭터, 정수, 실수등을 각 열거형 케이스에 제공할 수 있다.

 

스위프트에서 열거형은 그 자체로 일급 객체다. 컴퓨티드 프로퍼티(computed properties)나 인스턴스 메소드(instance method)와 같은, 기존에는 클래스에서만 사용할 수 있었던 많은 기능들을 가져왔고, 초기 케이스 값을 설정하는 이니셜라이저도 정의할 수 있으며, 프로토콜을 상속 받을 수도 있다.

 

Enumeration Syntax

열거형을 작성할 때는 enum 키워드를 사용하여 한 쌍의 중괄호 안에 작성한다.

enum SomeEnumeration {
    // enumeration definition goes here
}

다음 예시는 나침반의 동서남북 방향을 열거형으로 표현한 것이다.

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

north, south, east, west와 같이 열거형 안에 정의된 값들은 열거형 케이스이다. case 키워드를 이용하여 새로운 열거형 케이스를 작성할 수 있다.

 

한 줄에 다수의 케이스를 컴마(, )로 구분지어 작성할 수도 있다.

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

새로운 열거형의 정의는 새로운 타입을 정의하는 것과 같다. 스위프트의 다른 타입들처럼 열거형의 이름은 첫 문자를 대문자로 쓴다. 또한 이름을 단수형으로 쓰면 이 열거형이 자명하다는 것을 보일 수 있다.

var directionToHead = CompassPoint.west

directionToHead의 타입은 directionToHeadCompassPoint의 값중 하나로 초기화 되었으므로 추론이 가능하다. directionToHead가 한번 CompassPoint로 선언되었으니, 닷(.)을 이용하여 다른 CompassPoint의 값으로 설정 가능하다.

directionToHead = .east

이미 directionToHead의 타입을 알고 있으니 앞에 타입(CompassPoint)를 적어주지 않아도 된다.

 

Matching Enumeration Values with a Switch Statement

열거형의 값들을 switch 구문과 매치시킬 수 있다.

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")
}
// Prints "Watch out for penguins"

switch 구문은 반드시 exhaustive 해야 하므로, 모든 열거형 케이스를 하나라도 생략하면 컴파일할 수 없다. 하지만 모든 열거형 케이스를 명시적으로 다루기 힘들 때는 default 케이스를 사용하여 명시적으로 다루지 않은 나머지 케이스를 처리할 수 있다.

let somePlanet = Planet.earth
switch somePlanet {
case .earth:
    print("Mostly harmless")
default:
    print("Not a safe place for humans")
}
// Prints "Mostly harmless"

 

Iterating over Enumeration Cases

모든 열거형 케이스들을 담은 컬렉션이 필요한 경우가 있다. 이 때 열거형의 이름 옆에 : CaseIterable를 붙여주면  allCases 프로퍼티를 이용해 그러한 컬렉션을 사용할 수 있다.

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"

위 예시에선 Beverage.allCases를 사용해 Beverage 열거형의 모든 케이스를 가지고 있는 컬렉션에 접근 하고 있다. allCases는 원소가 enumeration 타입인 컬렉션처럼 사용된다(따라서 이 경우엔 컬렉션의 원소가 Beverage 값이다).

 

위의 예시는 얼마나 많은 케이스를 가졌는지 알아내는 코드이고, 아래의 예시에선 for in 루프를 사용해 모든 케이스를 반복(iterate)한다.

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

 

Associated Values

케이스들에 다른 타입의 값들을 저장하는 것은 유용하게 사용할 수 있다. 이런 추가 정보를 연관 값(associated value)라고 한다. 연관 값의 타입은 열거형의 각 케이스마다 다르게 만들 수도 있다.

 

UPC 포맷을 사용하는 1차원 바코드와 문자열을 사용하는 QR코드의 예시이다.

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

이 정의는 어떤 IntString값을 제공하지 않고 단지 Barcode.upcBarcode.qrCode의 연관 값의 타입만 정의한다.

 

연관 값의 타입을 이용해서 새로운 바코드를 만들 수 있다.

var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")

위 예시에서 Barcode.upc와 그 정수 값들은 새로운 Barcode.qrCode에 의해 문자열로 대체되었다. Barcode 타입의 상수나 변수는 .upc.qrCode를 연관 값과 함께 저장할 수 있지만. 한번에 그 둘 중 하나만 저장 가능하다.

 

switch 구문으로 연관 값을 추출 할 수 있다. switch 구문 케이스들의 본문에서 각각의 연관값을 let 키워드를 사용해서 상수로 추출하거나 var 키워드를 이용하여 변수로 추출할 수 있다.

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."

모든 연관값을 상수로만 추출하거나 변수로만 추출하는 경우에는 varlet을 case 이름 뒤에 한번만 써줘도 된다.

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."

 

이 글은 Apple의 The Swift Programming Language를 번역 및 재구성한 글입니다.
원저작물은 Creative Commons Attribution 4.0 International (CC BY 4.0) 라이선스를 따르며,
저작권은 © 2014–2023 Apple Inc. and the Swift project authors에게 있습니다.