Swift

열거형 (Enumerations)

데쿠! 2020. 11. 5. 00:03

/* The Swift Language Guide (한국어)를 공부합니다. */

열거형은 같은 특징을 가지는 값들을 하나의 그룹으로 관리하기 위한 개념입니다. 

열거형을 사용하면 type-safety를 보장할 수 있습니다.

( type-safety란, 하나의 enum 그룹의 요소 외에는 사용할 수 없도록 하는 것입니다.)

Swift에서는 C와 반대로 case값이 string, character, integer, floating 값을 사용할 수 있습니다. 

열거형은 1급 클래스 형이기 때문에 computed properties(계산된 프로퍼티)를 제공하거나, 초기 선언을 확장해 사용할 수 있습니다.


열거형 문법 (Enumeration Syntax)

enum키워드를 사용합니다.

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

-> Swift에서는 0, 1, 2, 3으 값을 갖지 않습니다.

-> 또한 콤마(,)를 이용하여 구분할 수 있습니다.

-> 열거형은 새로운 형(type)을 정의하는. 것이므로, 대문자로 시작해야 합니다.

 

var direction = CompassPoint.west
direction = .east

-> directiong형이 CompassPoint로 한번 정의가 되면, 다음부터는 dot을 이용해서 값을 할당할 수 있습니다.

 

Switch 구문에서 열거형 값 매칭 하기 (Matching Enumeration Values with a Switch Statement)

각 열거형을 switch구분을 이용하여 매칭 할 수 있습니다. 

direction = .south
switch direction{
    case .north:
    	print("north")
    case .south:
    	print("souoth")
    case .east:
    	print("east")
    case .west:
    	print("west")
}

-> switch 문을 사용하고 싶다면, 모든 case에 대해서 작성을 해야 합니다. 

direction = .south
switch direction{
    case .north:
    	print("north")
    case .south:
    	print("souoth")
    default:
    	print("default")
}

-> 만약 모든 case에 대해서 작성하고 싶지 않다면, default를 작성해줍니다.

 

관련 값 (Associated Values)

열거형의 각 case에 custom type의 추가적인 정보를 저장할 수 있습니다.

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

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

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

-> 관련 값을 이용하면 같은 형을 가지고 있지만, 다른 형태의 case를 설정할 수 있습니다.

 

 

Raw 값 (Raw Values)

case에 Raw 값을 지정할 수 있습니다.

enum ASCIIControlCharacter: Character {
    case tab = "\t"
    case lineFeed = "\n"
    case carriageReturn = "\r"
}

-> raw값은 열거형을 처음 선언할 때 정의되어서 각 case문들은 항상 같은 값을 가집니다. 

 

암시적으로 할당된 Raw 값 (Implicitly Assigned Raw Values)

enum Number: Int{
	case one = 1, two, three, four, five, six, seven, eight, nine, ten
}

-> 위와 같이 명시적으로 one에 1을 raw값으로 할당하였고, 그 이후의 변수에 대해서 암시적으로 1이 증가된 값이 할당됩니다. 

enum CompassPoint: String {
    case north, south, east, west
}

-> 위와 같이 String을 raw값으로 사용한다면 자동으로 각각의 case가 raw값으로 할당됩니다. (CompassPoint.south = "south")

 

let twoNumber = Number.two.rawValue
// two is 2

let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"

-> raw값은 rawValue프로퍼티를 사용해 접근할 수 있습니다.

 

 

Raw 값을 이용한 초기화 (Initializing from a Raw Value)

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

-> raw값을 이용하여서 열거형 변수를 초기화 할 수도 있습니다.

-> 만약 rawValue에 해당하는 값이 없다면 nil이 저장됩니다. 

 

 

재귀 열거자 (Recursive Enumerations)

재귀 열거자는 다른 열거 인스턴스를 관계 값으로 갖는 열거형입니다. case앞에 indirect키워드를 붙여 표시합니다.

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

-> 만약 모든 case에 indirect표시를 하고 싶다면 enum 키워드 앞에 indirect를 표시하면 됩니다.

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

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"

-> ( 5 + 4 ) * 2 를 처리하는 함수입니다.