switch 구문은 if와 guard 구문처럼 분기문의 일종이지만, 처리방식은 사뭇 다르다. switch 구문의 경우 입력받은 값을 조건식 여부가 아니라 패턴으로 비교하고 그 결과를 바탕으로 실행 블록을 결정하는 조건문이다. 나열된 패턴들을 순서대로 비교하다가 일치하는 첫 번째 패턴의 코드 블록을 실행한다.
굳이 switch 구문을 사용하지 않아도 if ~ else if 구문만으로도 작성이 가능하나 다양한 가능성이 있는 여러 개의 조건에는 switch 구문을 사용하는 것이 좀 더 효율적이다. switch 구문의 형태는 다음과 같다.
switch <비교 대상> {
case <비교패턴> :
<비교 패턴1이 일치했을 때 실행할 구문>
case <비교 패턴2>, <비교 패턴3> :
<비교 패턴2 또는 3이 일치했을 때 실행할 구문>
default :
<어느 비교 패턴과도 일치하지 않았을 때 실행할 구문>
}
스위프트의 case 구문은 C언어, 자바 등의 case 구문과 실행방식에 있어 차이점이 존재한다. C나 자바에선 비교패턴이 일치할 경우 우선 실행 구문을 처리한 다음(여기서 멈추려면 break를 넣어줘야함) 나머지 case에 대한 비교를 계속진행하고 추가로 일치하는 패턴이 있다면 또 실행하고 마지막 case를 비교한 후에 분기문을 종료한다.
하지만 스위프트의 switch 구문은 일치하는 비교패턴이 있을 경우 실행구문을 처리한 다음 더이상의 비교 없이 전체 분기문을 종료한다.(break없어도 알아서 종료됨) 추가적으로 일치하는 패턴이 여러개가 있다 하더라도 맨 처음 일치한 case 구문 하나만 실행한다. 다시 말해, 오직 하나의 case 구문만 처리하고 나면 더이상 비교를 진행하지 않는다는 것이다. break 구문을 스위프트에서 생략할 수 있는 것은 이 때문이다.
let val = 2
switch val {
case 1 :
print("일치한 값은 1입니다")
case 2 :
print("일치한 값은 2입니다")
case 2 :
print("일치한 값 2가 더 있습니다")
default :
print("어느 패턴과도 일치하지 않았습니다")
}
/* 실행결과
일치한 값은 2입니다
이 경우 6행에 있는 case 2와 일치하게되어 "일치한 값은 2입니다"를 출력하게 된다. 하지만 다음 8행에 작성한 case 2 역시 일치하는 패턴이 되는데 이 경우 스위프트의 switch 구문 특성상 이미 6행에서 일치했기 때문에 8행에서 일치하더라도 실행구문은 실행되지 않는다.
다른언어에서 이와같이 작성하였다면 이렇게 실행됐을 것이다.(일치한 값이 있더라도 계속 진행되기 때문)
/* 다른 언어에서의 실행 결과
일치한 값은 2입니다
일치한 값 2가 더 있습니다
어느 패턴과도 일치하지 않았습니다
이러한 상황을 방지하기위해 다른언어의 경우 반드시 break 구문을 추가해주어야 한다.
타 언어에서 사용되는 switch 구문을 살펴보면 스위프트와의 차이점을 떠 발견할 수 있다. switch 구문에는 패턴이 일치하는 case 블록을 실행하는 대신, 그 다음 case 블록으로 실행흐름을 전달하는 문법이 있는데, 이를 FallThrough라고 한다. 특히, 명시해주지 않아도 적용된다는 점에서 암시적인 FallThrough라고 한다. C 계열의 언어에서는 보통 다음과 같은 방식으로 작성된다.
let sampleChar : Character = "a"
switch sampleChar {
case "a" :
case "A" :
print("글자는 A입니다")
default:
print("일치하는 글자가 없습니다")
}
/* 실행결과
글자는 A입니다
암시적인 FallThrough가 적용되어 실행 흐름이 전달된 비교 블록은 패턴이 일치하지 않아도 실행블록을 처리하게된다. 따라서 위 예제에서는 4행의 case와 일치하지만 실행구문이 없기에 다음 6행이 실행된다.
그러나 스위프트에서는 이러한 암시적인 FallThrough를 지원하지 않는다. 뿐만 아니라 case 실행 블록이 비어 있는 것도 당연히 안 된다. 대신 명시적으로 FallThrough 구문을 사용함으로써 같은 결과를 얻을 수 있다.
let sampleChar : Character = "a"
switch sampleChar {
case "a" :
fallthrough
case "A" :
print("글자는 A입니다")
default :
print("일치하는 글자가 없습니다")
}
/* 실행결과
글자는 A입니다
switch 구문의 특성
스위프트에서 switch 구문에 사용된 비교 대상은 반드시 하나의 비교패턴과 일치해야한다. 비교 대상이 비교 패턴 중 어느 것과도 일치하지 않아 분기문 내의 어떤 블록도 실행되지 못하는 경우를 switch 구문이 실패했다고 부르는데, 스위프트는 이 같이 실패한 switch 구문을 완전한 비교패턴을 구성하지 못한 것으로 간주한다.
이에 따라 모든 case 구문에 일치된 패턴을 찾지 못했을 경우를 대비해 default 구문을 추가해야 하며, 만약 default를 생략하면 완전하지 않은 구문으로 간주해 오류가 발생한다. 단, default 구문을 대신해 모든 패턴을 매칭시킬 수 있는 구문이 존재하는 경우엔 default구문을 생략할 수도 있다.
case 비교 패턴을 작성할 때, 하나의 case 키워드 다음에 하나 이상의 비교 패턴을 연이어 작성할 수도 있다. 두 가지 이상의 패턴에 대해 같은 구문을 실행해야 한다면, 하나의 case 키워드로 비교 패턴을 묶어 표현하면 된다.
var value = 3
switch value {
case 0, 1 :
print("0 또는 1입니다")
case 2, 3 :
print("2 또는 3입니다")
default :
print("default입니다")
}
/* 실행결과
2 또는 3입니다
case 구문에서 사용되는 비교 패턴으로 단순히 서로 다른 패턴들 외에 튜플이나 특정 타입으로 캐스팅된 객체도 사용할 수 있다. switch 구문에서 튜플 내부의 아이템이 비교 대상과 부분적으로 일치할 경우, 스위프트는 case 구문의 비교 패턴 전체가 일치하는 것으로 간주하게 된다. 이 때 나머지 부분을 상수나 변수화 하여 사용할 수 있다. 다음 예제를 살펴보자.
var value = (2,3)
switch value {
case let (x, 3) :
print("튜플의 두 번쨰 값이 3일 때 첫번째 값은 \(x)입니다.")
case let (3, y) :
print("튜플의 첫 번째 값이 3일 때 두 번째 갓은 \(y)입니다.")
case let (x, y) :
print("튜플의 값은 각각 \(x), \(y)입니다")
}
/* 실행결과
튜플의 두 번째 값이 3일 때 첫 번째 값은 2입니다.
case 구문은 번위 연산자를 사용하여 해당 범위에 속하는 값을 매칭할 수도 있다.
var passtime = 1957
switch passtime {
case 0..<60 :
print("방금 작성된 글입니다")
case 60..<3600 :
print("조금 전 작성된 글입니다")
case 3600..<86400 :
print("얼마 전 작성된 글입니다")
default :
print("예전에 작성된 글입니다")
}
/* 실행결과
조금 전 작성된 글입니다
범위 연산자를 사용한 패턴 비교 방식은 튜플 형식의 데이터를 비교할 때에도 매우 유용하다.
var value = (2, 3)
switch value {
case (0..<2, 3) :
print("범위 A에 포함되었습니다")
case (2..<5, 0..<3) :
print("범위 B에 포함되었습니다")
case (2..<5, 3..<5) :
print("범위 C에 포함되었습니다")
default :
print("범위 D에 포함되었습니다")
}
/* 실행결과
범위 C에 포함되었습니다
뿐만 아니라 where 구문을 추가하면 각 case 블록별로 더 복잡한 패턴까지 확장할 수 있다.
var point = (3, -3)
switch point {
case let (x, y) where x == y :
print("\(x)과 \(y)은 x==y 선 상에 있습니다")
case let (x, y) where x == -y :
print("\(x)과 \(y)은 x==-y 선 상에 있습니다")
case let (x, y) :
print("\(x)과 \(y)은 일반 좌표상에 있습니다")
}
/* 실행결과
3과 -3은 x==-y 선 상에 있습니다
출처 : 꼼꼼한 재은씨의 Swift 문법편
'Swift > 문법' 카테고리의 다른 글
스위프트(Swift) - 집단 자료형(Collection Types) Ⅰ. 배열(Array) (0) | 2022.05.05 |
---|---|
스위프트(Swift) - 제어 전달문(Control Transfer Statements) (0) | 2022.05.04 |
스위프트(Swift) - 조건문 Ⅲ. #available 구문 (0) | 2022.05.02 |
스위프트(Swift) - 조건문 Ⅱ. guard 구문 (0) | 2022.04.30 |
스위프트(Swift) - 조건문 Ⅰ. if 구문 (0) | 2022.04.29 |