코틀린에서 when은 자바의 switch를 대체하는 키워드인데, 여러모로 더 편리합니다.

어떤 언어에서는 패턴매칭이라고도 하는데 사용법을 알아보겠습니다.

 

enum class Color(
    val r: Int,
    val g: Int,
    val b: Int,
) {
    RED(255, 0, 0),
    ORANGE(255, 165, 0),
    YELLOW(255, 255, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255),
    INDIGO(75, 0, 130),
    VIOLET(238, 130, 238),
    ;

    fun rgb() = (r * 256 + g) * 256 + b
}

일단 예제를 위해 enum 클래스를 하나 만들었습니다.

 

fun getMnemonic(color: Color) =
    when (color) {
        Color.RED -> "Richard"
        Color.GREEN -> "Gave"
        Color.ORANGE -> "Of"
        else -> "IDK :)"
    }

이런식으로 값을 매칭시킬 수 있습니다. when 내부가 모든 케이스를 커버한다면 else는 필요하지 않고, 빠진 케이스가 있다면 else를 써 줘야 합니다.

 

fun getWarmth(color: Color) =
    when (color) {
        Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
        Color.GREEN -> "neutral"
        Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
    }

여러 케이스를 매칭시킬 수도 있습니다. 위 예제에서는 모든 케이스가 커버되니 else가 없어도 됩니다

 

fun mix(c1: Color, c2: Color) =
    when(setOf(c1, c2)) {
        setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
        setOf(Color.YELLOW, Color.BLUE) -> Color.GREEN
        else -> throw Exception("Dirty Color!")
    }

when의 파라미터로 다른 객체를 사용할 수도 있습니다. 만들어 쓸 수도 있고, 아무 상관 없는 변수도 쓸 수 있습니다.

(위 예제처럼 만들면 호출될 때마다 여러 인스턴스를 생성하니 살짝 오버헤드가 있을 수도 있다고 하니 이 부분은 주의가 필요하겠네요)

 

when {
    x.isOdd() -> print("x is odd")
    y.isEven() -> print("y is even")
    else -> print("x+y is odd")
}

파라미터를 넣지 않고 분기 조건에 Boolean 값을 넣는 것도 됩니다

 

fun Request.getBody() =
    when (val response = executeRequest()) {
        is Success -> response.body
        is HttpError -> throw HttpException(response.status)
    }

코틀린 1.3부터는 when scope 안에서만 사용할 변수를 캡처할 수 있습니다. 덕분에 네임스페이스를 깔끔하게 유지할 수 있습니다

 

when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
}

조건에 is 키워드를 사용하면 스마트 캐스트(Smart cast)가 됩니다. 따로 캐스팅한 변수를 만들 필요가 없습니다

 

Reference

- https://kotlinlang.org/docs/control-flow.html#when-expression

- https://kotlinlang.org/docs/typecasts.html#smart-casts

반응형