enum
키워드를 사용해 열거형을 정의한다.
enum SomeEnumeration {
// enumeration definition goes here
}
다음은 네 가지 방향을 갖는 CompassPoint
열거형 선언의 예이다.
enum CompassPoint {
case north
case south
case east
case west
}
Swift에서 열거형은 생성될 때 각 case 별로 기본 integer 값을 할당하지 않는다.
여러 case를 콤마(,)로 구분해서 한줄에 적을 수 있다.
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn,uranus
}
각 열거형 정의는 완전 새로운 타입을 정의한다.
Swift의 다른 타입과 마찬가지로 타입의 이름은 대문자로 시작해야 한다.
var directionToHead = CompassPoint.west
directionToHead
의 타입은 CompassPoint
의 가능한 값 중 하나로 초기화 될 때 타입추론 된다.
한번 정의되면 다음에 값을 할당할 때 타입을 생략한 점(.) 문법을 이용해 값을 할당하는 축약형 문법을 사용할 수 있다.
directionToHead = .east
각 열거형 값을 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")
}
// "Watch out for penguins"
switch
문은 반드시 열거형의 모든 case
를 완전히 포함해야 한다. 만약 열거형의 모든 case의 처리를 기술하는게 적당하지 않다면 default
를 제공해 처리되지 않는 case
를 피할 수 있다.
let somePlanet = Planet.earth
switch somePlanet {
case .earth:
print("Home, sweet home...")
default:
print("Where am I?")
}
// "Home, sweet home..."
일부 열거의 경우 해당 열거의 모든 case
콜렉션을 갖는 것이 유용하다. 열거 이름 뒤에 CaseItable
을 작성하여 이 옵션을 사용하도록 설정한다. Swift는 모든 case
의 콜렉션을 열거 타입의 allCase
속성으로 표시한다.
enum Beverage: CaseIterable {
case coffee, tea, juice
case water
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "4 beverages available"
위의 예제는 Beverage
의 모든 case
가 포함된 콜렉션에 접근하는 경우이다. allCase
는 다른 콜렉션과 마찬가지로 사용할 수 있다. 콜렉션의 요소는 열거형 타입의 인스턴스이므로 이 경우에는 Beverage
값이다.
위의 예는 사례가 몇 개인지 세고, 아래 예제는 for-in
loop를 사용하여 모든 사례를 반복한다.
for beverage in Beverage.allCases {
print(beverage)
}
// coffee
// tea
// juice
// water
열거형의 각 case
에 custom type의 추각적인 정보를 저장할 수 있다.
바코드가 위와 같이 4가지 구분으로 이루어진 숫자로 이루어져 있거나, 2953개의 문자로 구성된 QR코드 형태로 이루어진 두 가지 동류가 있다면 이 바코드를 아래와 같은 열거형으로 정의할 수 있다.
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
관련값을 이용하면 위와 같이 같은 타입이지만, 다른 형태의 값을 갖는 case
를 만들 수 있다.
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
이렇게 선언하거나 아래처럼 선언할 수 있다.
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
관련값은 switch case
문에서 사용할 때 상수 혹은 변수로 선언할 수 있다.
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)")
}
// "QR code: ABCDEFGHIJKLMNOP"
case
안의 관련값이 전부 상수이거나 변수이면 공통된 값을 case
뒤에 선언해 보다 간결하게 기술할 수 있다.
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case let .qrCode(productCode):
print("QR code: \(productCode)")
}
// "QR code: ABCDEFGHIJKLMNOP"
case
에 raw 값을 지정할 수 있다.
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
위 예제에서는 Character
타입의 raw 값으로 정의했지만, String
, Character
, Integer
, Float
등의 타입을 사용할 수 있다.
단, 각 raw 값은 열거형 선언에서 유일한 값으로 중복되어서는 안된다.
Raw 값은 관계값과는 다르다. Raw 값은 코드에서 열거형을 처음 선언할 때 특정 열거형의 raw 값은 항항 같은 값을 갖는다. 하지만 관계값은 같은
case
라도 생성될 때 달라질 수 있다.
열거형을 다루면서 raw 값으로 Integer
, String
값을 사용할 수 있는데, 각 case
별로 명시적으로 raw 값을 할당할 필요는 없다.
만약 raw 값을 할당하지 않으면 Swift에서 자동으로 값을 할당한다.
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
위 경우 mercury에 1을 raw 값으로 명시적으로 할당했고 venus는 암시적으로 2 그리고 이후 값은 1 증가된 값을 자동으로 raw 값으로 할당 받는다.
만약 String
을 raw 값으로 사용한다면 case
텍스트가 raw 값으로 자동 할당 받는다.
enum CompassPoint: String {
case north, south, east, west
}
CompassPoint.south
는 암시적으로 "south"
를 raw 값으로 갖는다.
raw 값은 rawValue
프로퍼티를 사용해 접근할 수 있다.
let earthOrder = Planet.earth.rawValue
// earthOrder is 3
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"
raw 값을 이용해 열거형 변수에 초기값을 할당 할 수 있다.
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus
만약 열거형에 지정된 raw 값이 없는 값으로 초기자를 지정하면 그 값은 nil
이 된다.
let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
switch somePlanet {
case .earth:
print(Home, sweet home)
default:
print("Where am I?")
}
} else {
print("There is no planet at position \(positionToFind)")
}
// "There is no planet at position 11"
재귀 열거자는 다른 열거 인스턴스를 관계값으로 갖는 열거형이다. 재귀 열거자 case
는 앞에 indirect
키워드를 붙여 표시한다.
enum ArithmeticExpression {
case number (Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multipication(ArithmeticExpression, ArithmeticExpression)
}
만약 관계값을 갖는 모든 열거형 case
에 indirect
표시를 하고 싶으면 enum
키워드 앞에 표시하면 된다.
indirect enum ArithmeticExpression {
case number (Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multipication(ArithmeticExpression, ArithmeticExpression)
}
아래 예제는 (5 + 4) * 2 를 재귀 열거자로 표현한 것이다.
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let two = ArithmeticExpression.number(2)
let sum = ArithmeticExpression.addition(five, four)
// sum = 5 + 4 = 9
let product = ArithmeticExpression.multiplication(sum, two)
// product = 9 * 2 = 18
아래는 위 재귀 열거자를 처리하는 함수이다.
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 .multipication(left, right):
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
// Prints "18"