1. 코틀린의 조건문
- 코틀린은 두 가지 주요 조건문인
if와when을 제공합니다. - 자바와 달리 코틀린에서 이 조건문들은 표현식(expression)으로 사용될 수 있어 값을 반환할 수 있습니다.
- 여기서 표현식이란 값을 반환하는 코드 블록을 의미합니다.
- 반대로 구문(statement)은 값을 반환하지 않는 코드 블록을 의미합니다.
1.1 If 표현식
- 코틀린에서
if는 표현식이므로 값을 반환할 수 있습니다. - 이로 인해 자바의 삼항 연산자(
condition ? then : else)가 필요 없습니다.
1.1.1 기본 사용법
// 기본 형태
var max = a
if (a < b) max = b
// else 사용
if (a > b) {
max = a
} else {
max = b
}
// 표현식으로 사용
max = if (a > b) a else b
// else if 사용
val maxLimit = 1
val maxOrLimit = if (maxLimit > a) maxLimit else if (a > b) a else b
println("max is $max")
println("maxOrLimit is $maxOrLimit")
1.1.2 블록을 포함한 if 표현식
val max = if (a > b) {
print("Choose a")
a // 블록의 마지막 표현식이 반환값이 됩니다
} else {
print("Choose b")
b
}
if를 표현식으로 사용할 때(값을 반환하거나 변수에 할당할 때)는else분기가 필수입니다.if분기에 블록을 사용하는 경우 블록의 마지막 식이 그 분기의 값이 됩니다.
1.2 When 표현식
- if와 마찬가지로 값을 반환할 수 있는 표현식입니다.
when은 자바의switch와 유사하지만 더 강력한 기능을 제공합니다.- 여러 조건에 따라 코드를 실행하는 조건부 표현식입니다.
1.2.1 기본 사용법
val x = 2
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> print("x is neither 1 nor 2")
}
- 자바와 달리 각 분기의 끝에
break를 명시할 필요가 없습니다.
1.2.2 표현식과 구문으로서의 when
val text = when (x) {
1 -> "x == 1"
2 -> "x == 2"
else -> "x is neither 1 nor 2"
}
- 위는 표현식으로 사용(값을 반환)한 예시입니다.
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> print("x is neither 1 nor 2")
}
- 구문으로 사용 (값을 반환하지 않음)한 예시입니다.
1.2.3 주체가 있는 when과 없는 when
when(x) { ... }
- 위는 주체가 있는 when의 예시입니다.
- when 식의 인자로 아무 객체나 사용할 수 있습니다.
- 인자로 받은 객체가 각 분기 조건에 있는 객체와 같은지 비교합니다.
- when 식은 인자 값과 일치하는 조건 값을 찾을 때까지 각 분기를 검사합니다.
- 분기 조건에 있는 객체를 비교할 때 동등성을 사용합니다.
when {
a > b -> "a is greater than b"
a < b -> "a is less than b"
else -> "a is equal to b"
}
- 주체가 없는 when의 예시입니다.
- when에 아무 인자가 없으면 각 분기의 조건이 불리언 결과를 계산하는 식이어야 합니다.
경고
when을 표현식으로 사용할 때는 모든 가능한 경우를 처리해야 합니다. 즉, 철저해야(exhaustive) 합니다. 모든 경우를 처리하지 않으면 컴파일러는 오류를 발생시킵니다.
1.2.4 다양한 when 사용법
- 여러 조건을 한 줄에 콤마로 결합:
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
- 임의 표현식을 조건으로 사용:
when (x) {
s.toInt() -> print("s encodes x")
else -> print("s does not encode x")
}
- 범위나 컬렉션 내 포함 여부 확인:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
- 타입 확인(스마트 캐스트 지원):
fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix") // x가 자동으로 String으로 캐스팅됨
else -> false
}
- if-else if 체인 대체:
when {
x.isOdd() -> print("x is odd")
y.isEven() -> print("y is even")
else -> print("x+y is odd")
}
- 주체 변수 캡처:
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}
1.3 가드 조건(Guard Conditions)
실험적 기능
가드 조건은 실험적 기능으로 언제든지 변경될 수 있습니다.
- 가드 조건을 사용하면 when 표현식의 분기에 여러 조건을 포함할 수 있습니다.
- 주체가 있는 when 표현식이나 구문에서 사용할 수 있습니다.
기본 사용법
sealed interface Animal {
data class Cat(val mouseHunter: Boolean) : Animal
data class Dog(val breed: String) : Animal
}
fun feedAnimal(animal: Animal) {
when (animal) {
// 기본 조건만 있는 분기
is Animal.Dog -> feedDog()
// 기본 조건과 가드 조건이 모두 있는 분기
is Animal.Cat if !animal.mouseHunter -> feedCat()
// 위 조건 중 어느 것도 일치하지 않을 경우
else -> println("Unknown animal")
}
}
가드 조건의 특징
- 가드 조건이 있는 분기의 코드는 기본 조건과 가드 조건이 모두 true로 평가될 때만 실행됩니다.
- 기본 조건이 일치하지 않으면 가드 조건은 평가되지 않습니다.
- 가드 조건은 else if도 지원합니다:
when (animal) {
is Animal.Dog -> feedDog()
is Animal.Cat if !animal.mouseHunter -> feedCat()
else if animal.eatsPlants -> giveLettuce()
else -> println("Unknown animal")
}
- 논리 연산자를 사용해 여러 가드 조건을 결합할 수 있습니다:
when (animal) {
is Animal.Cat if (!animal.mouseHunter && animal.hungry) -> feedCat()
}
가드 조건 활성화 방법
- CLI에서 활성화:
kotlinc -Xwhen-guards main.kt
- Gradle에서 활성화:
// build.gradle.kts 파일에 추가
kotlin.compilerOptions.freeCompilerArgs.add("-Xwhen-guards")
2. 코틀린의 반복문
- 코틀린은 다양한 종류의 반복문을 제공하여 컬렉션이나 범위를 효율적으로 순회할 수 있습니다.
2.1 For 루프
- 코틀린의
for루프는 이터레이터를 제공하는 모든 것을 순회할 수 있습니다. - C#의
foreach루프와 유사합니다.
2.1.1 기본 사용법
for (item in collection) print(item)
// 블록을 사용한 for 루프
for (item: Int in ints) {
// 코드
}
2.1.2 범위를 이용한 반복
// 1부터 3까지 반복
for (i in 1..3) {
print(i)
}
// 6부터 0까지 2씩 감소하며 반복
for (i in 6 downTo 0 step 2) {
print(i)
}
// 출력: 1236420
2.1.3 배열이나 리스트를 인덱스와 함께 순회
// 인덱스를 사용한 순회
for (i in array.indices) {
print(array[i])
}
// withIndex 함수를 사용한 순회
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
팁
배열이나 범위에 대한 for 루프는 인덱스 기반 루프로 컴파일되어 이터레이터 객체를 생성하지 않으므로 성능 면에서 유리합니다.
2.2 While 루프
- 코틀린은
while과do-while두 가지 형태의 while 루프를 제공합니다. - 두 루프의 차이점은 조건 검사 시점입니다.