출처 - https://tourspace.tistory.com/99?category=797357
2.3 enum 과 when
2.3.1 enum
enum은 아래와 같이 사용합니다.
enum class Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
물론 이건 기본적인 형태이지만, 흔히 java에서 사용할때 enum값 내부에 멤버변수를 설정하기도 합니다.
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
}
fun main(args: Array) {
println(Color.BLUE.rgb())
}
num 내부에 값과 함수까지 정의했습니다.
코틀린에서는 ; 를 사용하지 않지만 enum의 마지막에는 꼭 사용해야합니다.
2.3.2 when에 enum을 사용
when은 자바와 다르게 좀더 확장성 있게 object를 지원합니다.
enum은 java에서도 지원하고, 당연히 kotlin에서 지원합니다.
fun getMnemonic(color: Color) = when (color) {
Color.RED -> "Richard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Gave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
fun main(args: Array) {
println(getMnemonic(Color.BLUE))
}
when의 특징은 break;를 넣지 않아도 된다는 점입니다.
따라서 break를 빼먹어서 생기는 오류를 막을 수 있습니다.
만약에 여러값을 하나의 분기로 처리하고자 한다면 콤마 "," 를 사용하면 됩니다.
fun getWarmth(color: Color) = when(color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
Color.GREEN -> "neutral"
Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
2.3.3 when의 인자로 object 사용
when은 object를 인자로 받을수 있기 때문에 아래와 같은 활용도 가능합니다.
fun mix(c1: Color, c2: Color) =
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
else -> throw Exception("Dirty color")
}
fun main(args: Array) {
println(mix(BLUE, YELLOW))
}
setOf는 java로 얘기하면 set을 만드는 함수 입니다.
(HashSet으로 생각하시면 편하겠네요~)
c1과 c2에 들어오는 순서는 상관이 없습니다.
예를들어 mix(RED, YELLOW) 와 mix(YELLOW, RED) 는 둘다 ORANGE가 반환됩니다.
또한 else를 사용하여 남은 처리를 할수도 있습니다.
이렇게 when을 사용하면 if ~ else, switch를 대체하여 좀더 간결하고 직관적인 코드를 작성할 수 있습니다.
2.3.4 인자없는 when
위 경우에는 전부 when에 인자값을 넣어서 사용했으나, 인자값 없이도 사용할 수 있습니다.
단! when에 인자가 없다면, 조건부분은 반드시 Boolean을 반환하는 expression이어야 합니다.
fun mixOptimized(c1: Color, c2: Color) =
when {
(c1 == RED && c2 == YELLOW) || (c1 == YELLOW && c2 == RED) -> ORANGE
(c1 == YELLOW && c2 == BLUE) || (c1 == BLUE && c2 == YELLOW) -> GREEN
(c1 == BLUE && c2 == VIOLET) || (c1 == VIOLET && c2 == BLUE) -> INDIGO
else -> throw Exception("Dirty color")
}
fun main(args: Array) {
println(mixOptimized(BLUE, YELLOW))
}
setof를 빼면서 불필요 객체 생성은 막았지만, 왠지 복잡해 보이는군요.
이전 코드가 가독성은 더 좋아 보입니다.^^a
2.3.5 스마트 캐스트 (smart cast)
코틀린의 장점중 하나는 스마트 캐스트를 지원한다는 점입니다.
스마트 캐스트란 object의 타입 확인과 변환을 한번에 해주는 기능입니다.
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인 right, left에 바로 접근할 수 있다.
}
throw IllegalArgumentException("Unknown expression")
}
fun main(args: Array) {
println(eval(Sum(Sum(Num(1), Num(2)), Num(4))))
}
위 예제를 보면 Num과 Sum은 모두 Expr 이라는 interface를 구현하고 있습니다.
is 는 instanceof와 같은 역할이라고 보면 되며 as는 강제 캐스팅이라고 보면 됩니다.
위에서 if (e is Num) 을 통과하여 내부 블럭으로 들어왔다면 e as Num 을 해줄 필요가 없습니다.
사실 이미 내부 블럭에서 e는 컴파일러에 의해 Num으로 이미 자동 캐스팅된 상태입니다.
이 코드를 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")
}
if를 써도 되지만 when을 쓰는게 좀더 간결합니다.
2.3.7 if문과 when에서의 블럭사용
if문과 when문은 블럭을 사용해서 표현할 수 도 있습니다.
이때 마지막 문장이 블럭 전체의 결과값이 됩니다!!
fun evalWithLogging(e: Expr): Int =
when (e) {
is Num -> {
println("num: ${e.value}")
e.value
}
is Sum -> {
val left = evalWithLogging(e.left)
val right = evalWithLogging(e.right)
println("sum: $left + $right")
left + right
}
else -> throw IllegalArgumentException("Unknown expression")
}
'개발 > 코틀린(kotlin)' 카테고리의 다른 글
[Kotlin] 코틀린의 기초 #4 exception 처리 (0) | 2020.01.28 |
---|---|
[Kotlin] 코틀린의 기초#3 iteration, for, while, in (0) | 2020.01.28 |
[Kotlin] 코틀린의 기초#1 - 함수,변수,클래스,property (0) | 2020.01.28 |
[Kotlin] 코틀린이란? (0) | 2020.01.28 |
kotlin android extensions (0) | 2020.01.27 |
댓글