나의 기록, 현진록

[Swift] 6.1.2 switch 구문 본문

Programming/Swift

[Swift] 6.1.2 switch 구문

guswlsdk 2021. 7. 5. 11:57
반응형

스위프트 프로그래밍 3판 - 야곰 지음

 

6.1.2 switch

swift에서 기본 문법인 switch 구문은 다른 언어와 비교하였을 때 많이 달라진 문법 중 하나이다. 소괄호를 생략할 수 있으며, break 키워드를 사용하지 않아도 case 내부의 코드를 모두 실행하면 switch 구문이 종료된다. 만약 case를 연속하여 실행하고 싶을 경우 fallthrough 키워드를 사용한다.

 

swift에서 switch 구문의 조건에 다양한 값이 들어갈 수 있습니다. (C언어에서는 정수 타입만 들어갈 수 있음) 다만 각 case에 들어갈 비교 값은 입력 값과 데이터 타입이 같아야 한다. 또, 비교될 값이 명확히 한정적인 값(열거형 등)이 아닐 때는 default를 꼭 작성해야 한다. 각 case에는 범위 연산자를 사용할 수도, where 절을 사용하여 조건을 확장할 수도 있습니다.

 

switch value {
case pattern1:
    //실행 구문
case pattern2:
    //실행 구문
    fallthrough // case를 마치고 switch 구문을 탈출하지 않는다.
case pattern3, pattern4:
    //실행 구문
default: //한정된 범위가 명확지 않다면 default 작성은 필수이다.
    //실행 구문
    
}

 

간단한 예제이다.

 

let intergerValue: Int = 5
switch intergerValue {
case 0:
    print("Value == zero")
case 1...10:
    print("Value == 1~10")
    fallthrough // case를 마치고 switch 구문을 탈출하지 않는다.
case Int.min..<0, 101..<Int.max:
    print("Value < 0 or Value > 100")
default: //한정된 범위가 명확지 않다면 default 작성은 필수이다.
    print("10 < Value <= 100")
    
}

case 3는 조건 값에 맞지 않지만 case 2에서 fallthrough 키워드를 사용하였기 때문에 실행된 모습이다.

 

 

 

부동소수 타입의 범위 연산을 통한 case를 구성하였다.

 

let doubleValue: Double = 3.0
switch doubleValue {
case 0:
    print("Value == zero")
case 1.5...10.5:
    print("1.5 <= Value <= 10.5")
default: //한정된 범위가 명확지 않다면 default 작성은 필수이다.
    print("Value == \(doubleValue)")
}

 

 

case xxx: 다음에는 꼭 실행 가능한 코드가 위치해야 한다는 점을 명심하자.

 

 

 

switch 구문의 입력 값으로 숫자 표현이 아닌 문자, 문자열, 열거형, 튜플, 범위, 패턴이 적용된 타입 등 다양한 타입의 값도 사용 가능하다.

 

 

 

다음은 와일드카드 식별자를 사용한 튜플 switch case 구성이다.

 

let tupleValue: (name: String, age: Int) = ("yagom", 99)

switch tupleValue {
case ("yagom", 50):
    print("정확히 맞췄습니다.")
case ("yagom", _):
    print("이름만 맞췄습니다. 나이는 \(tupleValue.age)입니다.")
case (_, 99):
    print("나이만 맞췄습니다. 이름은 \(tupleValue.name)입니다.")
default:
    print("누굴 찾나요?")
}

 

이처럼 와일드카드 식별자를 사용하면 무시된 값을 직접 가져와야 하는 불편함이 있을 수 있습니다. 그 때 let을 붙인 값 바인딩을 사용합니다.

 

let tupleValue: (name: String, age: Int) = ("yagom", 99)

switch tupleValue {
case ("yagom", 50):
    print("정확히 맞췄습니다.")
case ("yagom", let age):
    print("이름만 맞췄습니다. 나이는 \(age)입니다.")
case (let name, 99):
    print("나이만 맞췄습니다. 이름은 \(name)입니다.")
default:
    print("누굴 찾나요?")
}

 

 

열거형과 같이 한정된 범위의 값을 조건으로 받게 되면 default를 구현하지 않아도 됩니다. 그러나 만약 값에 대응하는 각 case를 구현하지 않는다면 default는 필수입니다.

enum School{
    case primary //유치원
    case elementary //초등
    case middle //중등
    case high //고등
    case college //대학
    case university //대학교
    case graduate //대학원
}

let 최종학력: School = School.university

switch 최종학력 {
case .primary:
    print("최종학력은 유치원입니다.")
case .elementary:
    print("최종학력은 초등학교입니다.")
case .middle:
    print("최종학력은 중학교입니다.")
case .high:
    print("최종학력은 고등학교입니다.")
case .college, .university:
    print("최종학력은 대학(교)입니다.")
case .graduate:
    print("최종학력은 대학원입니다.")    
}

 

 

만약 이 때 열거형에 case가 추가될 가능성이 있다면 switch 구문에서 어떻게 대비해야 할지 알아보자.

unknown 속성을 사용해보자.

 

enum Menu{
    case chicken
    case pizza
}

let lunchMenu: Menu = .chicken

switch lunchMenu {
case .chicken:
    print("반반 무 많이")
case .pizza:
    print("핫소스 많이 주세요.")
default:
    print("오늘 메뉴가 뭐죠?")
}

 

이렇게 하면 Menu 열거형에 case를 추가해도 default가 있기 때문에 컴파일 오류가 발생하지는 않을 것입니다. 그러나 경고를 표시해주긴 합니다.

 

그런데 만약 미래에 Menu 열거형에 새로운 case를 추가하고 switch 구문을 수정하지 않았을 경우엔 논리적 오류가 발생할 수 있기 때문에 이를 방지하기 위해 unknown이 필요합니다.

 

 

enum Menu{
    case chicken
    case pizza
    case hambuger
}

let lunchMenu: Menu = .chicken

switch lunchMenu {
case .chicken:
    print("반반 무 많이")
case .pizza:
    print("핫소스 많이 주세요.")
@unknown case _: //case _는 default와 같다.
    print("오늘 메뉴가 뭐죠?")
}

 

 

unknown을 사용하면 switcg 구문이 모든 case에 대응하지 않는다는 사실을 상기할 수 있으며 논리적인 오류에 대해 피드백 받을 수 있다. unknown 속성을 부여 받은 case는 가장 마지막 case로 작성해야 한다.

 

 

 

반응형