• [Kotlin In Action] 선택 표현과 처리 when
    언어/Kotlin 2022. 4. 23. 23:24
    반응형

     kotlin의 when문은 java의 switch와 비슷한 역할을 하지만 훨씬 더 강력한 프로그래밍적 요소이다. 2개 이상의 분기가 필요할 때 when문을 사용하게 된다. 책에서는 enum클래스로 예시를 들었으나 Boolean(true, false), enum, sealed class3가지 타입 모두 else없는 when을 작성할 수 있다.

    1. when으로 enum 클래스 다루기

    enum으로 정의된 Color 값을 받아서 색상에 대한 문자열 값을 반환하는 기능을 만들어보면 다음과 같다.

    enum class Color {
       RED, YELLOW, GREEN, BLUE, SKY,
    }
    fun getColorName(color: Color): String = when (color) {
        Color.RED -> "RED"
        Color.YELLOW -> "YELLOW"
        Color.GREEN -> "GREEN"
        Color.BLUE -> "BLUE"
        Color.SKY -> "SKY"
    }

    만약 아래 두 줄을 삭제하면 어떻게 되는가?

        Color.BLUE -> "BLUE"
        Color.SKY -> "SKY"

      여기서 중요한 점은 enum으로 정의된 Color의 모든 색 타입이 when에 정의되어야 한다는 것이다. Color.BLUE, Color.SKY의 값이 파라미터로 넘어온다면 별도 처리가 필요하기 때문에, 아래 코드는 컴파일 오류가 발생한다.

    fun getColorName(color: Color): String = when (color) {
        Color.RED -> "RED"
        Color.YELLOW -> "YELLOW"
        Color.GREEN -> "GREEN"
        // compile error
    }

     

    이를 해결하기 위해서 else를 써줄 수 있다. 

    fun getColorName(color: Color): String = when (color) {
        Color.RED -> "RED"
        Color.YELLOW -> "YELLOW"
        Color.GREEN -> "GREEN"
        else -> "ETC"
    }

    한 분기에 여러 패턴을 매치하고 싶다면 (,)콤마를 사용 할 수 있다.

    fun getColorName(color: Color): String = when (color) {
        Color.RED, Color.YELLOW -> "RED&YELLOW"
        Color.GREEN -> "GREEN&BLUE"
        Color.SKY -> "SKY"
    }

    2. when과 임의의 객체를 함께 사용

    1.에서의 enum으로 정의된 Color값 두 가지를 받아서 색을 조합하는 기능을 만들어보면 다음과 같다.

    fun getColorName(color1: Color, color2: Color): Color = when (setOf(color1, color2)) {
        setOf(Color.RED, Color.GREEN) -> Color.YELLOW // setOf(Color.GREEN, Color.RED)도 통과
        setOf(Color.GREEN, Color.BLUE) -> Color.SKY // setOf(Color.BLUE, Color.GREEN)도 통과
        else -> throw Exception("Dirty color")
    }

    3. 인자 없는 when

    2.에서 색 조합 예제를 인자 없는 when으로 바꾸면 다음과 같다.

    fun getColorName(color1: Color, color2: Color): Color = when (setOf(color1, color2)) {
        (color1 == Color.RED && color2 == Color.GREEN) ||
        (color1 == Color.GREEN && color2 == Color.RED) -> 
          Color.YELLOW
        (color1 == Color.GREEN && color2 == Color.BLUE) ||
        (color1 == Color.BLUE && color2 == Color.GREEN) -> 
          Color.SKY
        else -> throw Exception("Dirty color")
    }

     가독성이 많이 떨어지지만 setOf()를 이용해 Set객체를 만들지않으므로 속도면에서 빠르다. 가독성을 포기할 만큼, 성능이 중요한 기능이 아니라면 가독성을 포기하진 말자.

    반응형

    댓글

Designed by Tistory.