본문 바로가기
Kotlin

Kotlin enum과 when

by 봄석 2019. 1. 23.

Kotlin enum과 when


enum

enum은 열거형(enumerated type)이라고 부른다. 열거형은 서로 연관된 상수들의 집합이라고 할 수 있다.

enum은 아래와 같이 사용합니다.

enum class Color{
    RED,ORANGE,YELLOW,GREEN,BLUE,INDIGO
}



위는 기본적인 형태이고, 흔히 자바에서 사용할땐

enum값 내부에 멤버 변수를 설정하기도 합니다.

enum class Color{
    RED(255,0,0),ORANGE(255,165,0),YELLOW(255,255,0),GREEN(0,255,0),BLUE(0,0,255),INDIGO(75,0,130)
 
    fun rgb()=(r*256+g) *256+b
}
 
fun main(args:Array){
    println(Color.BLUE.rgb())
}


enum 내부에 값과 함수까지 정의했습니다.

코틀린에서는 ;를 사용하지 않지만 enum의 마지막에는 반드시 사용해야 합니다.


when에 enum을 사용

fun getMnemoic(color:Color)=when(color){
    Color.RED->"Richard"
    Color.ORANGE->"Of"
    Color.YELLOW->"York"
    Color.GREEN->"Gave"
    Color.BLUE->"Battle"
    Color.INDIGO->"In"
}
fun main(agrs:Array){
    println(getMnemonic(Color.BLUE))
}


when의 특징은 break를 넣지않아도 된다는 점입니다.


만약 여러값으로 분기하고자 한다면 "," 콤마를 사용하면 됩니다.


when의 인자로 Object 사용하기

when은 object를 인자로 받을 수 있기 때문에 아래와 같은 사용도 가능합니다

fun getMnemoic(color:Color)=when(color){
    Color.RED,Color.ORANGE->"Richard"
    Color.YELLOW->"York"

}


fun mix(c1:Color,c2:Color)=when(setOf(c1,c2)){
    setOf(RED,YELLOW)->ORANGE
    setOf(YELLOW,BLUE)->GREEN
    else->throw Exception("Dirty color")
}
 
fun main(args:Array){
    println(mix(BLUE,YELLOW))    
}


\

setOf는 java로 이야기하면 set을 만드는 함수입니다.


c1과 c2에 들어오는 순서는 상관없이

mix(REX,YELLOW)와 mix(YELLOW,RED)는 둘다 상관없이 ORANGE가 반환됩니다.

또한 else를 이용하여 남은 처리를 할 수도 있습니다.


인자없는 when

fun mixOptimized(c1:Color,c2:Color)=
    when{
        (c1 ==RED && c2 ==YELLOW) ||
        (c1 ==YELLOW && c2 ==RED)->
            ORANGE
            ....
 
        else ->throw Exception("Dirty color")
    }
 
fun main (args:Array){
    println(mixOptimized(BLUE,YELLOW))

}

인자값 없이 when을 사용하는경우에는 조건부분은 반드시 Boolean을 반환하는 expression 이여야 합니다.


스마트 캐스트

코틀린의 장점중 하나는 스마트캐스트를 지원한다는 점입니다.

스마트 캐스트란 obejct의 타입 확인과 변환을 한번에 해주는 기능입니다.

interface Expr //아무함수도 없는 Dummy interface를 만든다
class Num(val value:Int):Expr
class Sum(val left:Expr, val right:Expr):Expr
 
fun eval(e:Expr):Int{
    if(e is Num){    //smart Cast가 발생한다
        val n= e as Num     //e를 Num Type으로 전환하지만 , 이미 smart cast 되어 Num 타입입니다(생략가능)
        return n.value
    }
    if (e is Sum){ //smart Cast가 발생한다
                //이미 e는 Sum type으로 변환된 상태이므로 as를 이용하여 변환할 필요가 없다
        return eval(e.right) + eval(e.left) //sum의 property에 바로 접근 가능
    }
    throw IllegalArgumentException("Unkown expression")
}
 
fun main(args:Array){
    prinln(eval(Sum(Sum(Num(1),Num(2),Num(4))))
}


위 예제를 보면 Num과 Sum은 모두 Expr 이라는 interface를 구현하고 있습니다.

is 는 instanceof와 같은 역할이라고 보면 되며 as는 강제 캐스팅이라고 보면 됩니다.


if를 써도 되지만 when을 쓰면 더 간결합니다.

fun eval(e:Expr):Int=
    when(e){
        is Num->
            e.value
        is Sum->
            eval(e.right)+eval(e.left)
        else->
            throw IllegalArgumentException("Unknown expression")
    }
}


댓글