Swift - 열거형

임성빈·2022년 3월 11일
0

Swift

목록 보기
8/26
post-thumbnail
post-custom-banner

열거형 문법

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

Swift 구문에서 열거형 값 매칭

각 열거형 값을 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의 반복

일부 열거의 경우 해당 열거의 모든 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"

Raw 값

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 값

열거형을 다루면서 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 값을 이용한 초기화

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)
}

만약 관계값을 갖는 모든 열거형 caseindirect 표시를 하고 싶으면 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"
profile
iOS 앱개발
post-custom-banner

0개의 댓글