swift

swift - Enumerations(RawValue, Associated Value, Enumeration case Pattern)

행복하게사는게꿈 2021. 1. 7. 19:18

Enumerations(열거형)

// 열거형
// 열거형에 포함된 상수들은 상수라고 부르지 않고 Enumeration case 혹은 case로 부름
// 코드의 가독성, 안정성 향상

// 열거형을 사용하지 않았을때 발생하는 오류

//let left = 0
//let center = 1
//let right = 2
//
//var aligment = center


// 규칙을 모르더라도 값만으로 어떤 의미인지 파악할 수 있게

// 가독성은 증가했지만 문자열이기 때문에 오타가 발생할 수도 있고 비교 기준을 명확히해야함(대소문자 등)
let left = "left"
let center = "center"
let right = "right"

var aligment = center

// 대문자라서 false
if aligment == "Center" {
    
}

// 열거형 case는 독립적인 값
enum Alignment {
    case left
    case right
    case center
}

Alignment.center

var textAlignment = Alignment.center
print(textAlignment)

// 앞에서 열거형을 작성했기 때문에 어떤 열거형인지 추론할 수 있기 때문에 .left만 적어줘도 된다.
textAlignment = .left

// enum case는 값이기 때문에 == 으로 구분한다.
if textAlignment == .center {
    
}

//switch
switch textAlignment {
case .left:
    print("left")
case .right:
    print("right")
case .center:
    print("center")
}

Raw Values

// 원시값
// case와 함께 다른 값을 선언해야 할때 사용

enum Alignment: Int {
    //  Int가 raw Value이고 값을 지정해주지 left부터 순서대로 0 1 2
    case left
    case right
    case center
    case leftInt = 5
    case rightInt  // 요곤 그전 값 +1
}

Alignment.leftInt.rawValue
Alignment.left.rawValue
Alignment.rightInt.rawValue

// rawValue에 새로운 값 넣는거 불가능
// Alignment.right.rawValue = 5

// rawValue에 해당하는 case 리턴됨
Alignment(rawValue: 5)

// rawValue에 해당하는 값 없으면 nil
Alignment(rawValue: 200)



enum Weekday: String {
    case sunday
    case monday = "MON"
    case tuesday
    case wednesday
    case thursday
    case friday
    case saturday
}
// rawValue가 String이면 case에 해당하는 String리턴
Weekday.sunday.rawValue

// 값이 있으면 지정한 값 리턴
Weekday.monday.rawValue


// rawValue를 Character로 선언한 경우에는 반드시 rawValue를 직접 지정해야 한다.
enum ControlChar: Character {
    case tab = "\t"
    case newLine = "\n"
}

Associated Value

// enum case에 연관된 값을 저장한다.
enum VideoInterface: String {
    case dvi = "1028x768"
    case hdmi = "2048x1536"
    case displayPort = "3840x2160"
}

// 이렇게하면 문자를 숫자로 추출해야한다.
// 이렇게 원시값으로 해상도를 저장하면 전부 공유



// associated Values
// 1. 저장할 자료형을 개별 case별로 가능
// 2. () 튜플로 선언
// 3. case뒤에 선언
// 4. 선언할 수 있는 형식에 제한이 없음
// 5. 하나의 케이스에서 서로 다른 자료형을 선언할 수 있음

enum AssociatedVideoInterface {
    // named Tuple로 선언가능
    case dvi(width: Int, height: Int)
    // Unnamed Tuple로도 선언가능
    case hdmi(Int, Int, Double, Bool)
    case displayPort(CGSize)
}

var input = AssociatedVideoInterface.dvi(width: 2048, height: 1536)

// 연관값을 코드로 확인할 때는 주로 switch문을 사용
// enumeration case parttern
switch input {
case .dvi(width: 2048, height: 1536):
    print("dvi 2048 x 1536")
case .dvi(2048, _): // 와일드 카드 패턴으로 높이를 생략
    print("div 2048 x Any")
case .dvi: // 연관값 무시하고 case만 일치시킬 때
    print("dvi")
case .hdmi(let width, let height, let version, let audioEnabled): // 연관값을 상수로 바인딩
    print("hdmi \(width)x\(height)")
case let .displayPort(size): // 모든 연관 값을 동일한 case로 바인딩 하는 경우
    print("dp")

}

input = .hdmi(3080, 2160, 2.1, true)
input

Enumberation Pattern

// Enumeration Case Pattern
// 연관값을 가진 열거형 case를 매칭시킬때 사용
// switch, if, guard, for-in문에서 사용

enum TransPortation {
    case bus(number: Int)
    case taxi(company: String, number: Int)
    case subway(lineNumber: Int, express: Bool)
}

var tpt = TransPortation.bus(number: 7)

// swich문에서 enumeration case pattern
switch tpt {
case .bus(let n): // bus case를 매칭시키고 연관값은 n 상수에 바인딩
    print(n)
case .taxi(let c, var n):
    print(c, n)
case let .subway(l, e):
    print(l, e)
}

tpt = TransPortation.subway(lineNumber: 2, express: false)

// if문에서 enumeration case pattern
if case let .subway(2, express) = tpt { // .subway의 lineNumber가 2 일때 true
    if express {
        
    } else {
        
    }
}

// 지금은 값을 바인딩하지 않아서 case 뒤에 let 이나 var 키워드를 쓰지 않음
if case .subway(_, true) = tpt {
    print("express")
}

let list = [
    TransPortation.subway(lineNumber: 2, express: false),
    TransPortation.bus(number: 4412),
    TransPortation.subway(lineNumber: 7, express: true),
    TransPortation.taxi(company: "SeoulTaxi", number: 1234)
]

for case let .subway(n, _) in list {
    print("subway \(n)")
}

for case let .subway(n, true) in list {
    print("subway \(n)")
}

for case let .subway(n, true) in list where n == 2 {
    print("subway \(n)")
}