Kotlin/Kotlin inAction 책 읽기
[코틀린] 코틀린 기초 - 선택 표현과 처리: enum과 when
Na선생
2025. 4. 1. 13:07
선택 표현과 처리: enum과 when
1. enum 클래스 정의
Kotlin에서는 enum 클래스를 사용하여 열거형을 정의할 수 있다.
enum class Color {
RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}
- enum은 특별한 의미를 가지는 소프트 키워드로, class 키워드 앞에서만 특별한 의미를 가짐.
- 각 항목은 자동으로 객체 인스턴스화되며, 순서와 이름을 가짐.
1.1 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
}
println(Color.BLUE.rgb())
- 생성자와 프로퍼티를 선언하여 색상 값을 저장.
- 각 열거형 상수에서 해당하는 RGB 값을 전달해야 함.
- rgb() 메서드를 정의하여 RGB 값을 계산 가능.
- 열거형 상수 목록과 메서드 사이에는 반드시 ;(세미콜론)가 필요.
2. when과 enum 클래스
when은 Java의 switch와 유사하지만 더욱 강력한 기능을 제공한다.
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"
}
println(getMnemonic(Color.BLUE))
- when은 값을 반환하는 식(expression) 으로 사용 가능.
- 각 분기에서 break를 명시할 필요 없음.
2.1 여러 값 처리
when을 사용하면 하나의 분기에 여러 값을 설정할 수 있다.
fun getWarmth(color: Color) = when (color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
Color.GREEN -> "neutral"
Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
println(getWarmth(Color.ORANGE))
- ,를 사용하여 여러 값에 대해 동일한 결과를 반환 가능.
3. when과 임의 객체
when을 사용하여 두 개의 색상을 조합하는 예제를 만들어 보자.
fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) {
setOf(Color.RED, Color.YELLOW) -> Color.ORANGE
setOf(Color.YELLOW, Color.BLUE) -> Color.GREEN
setOf(Color.BLUE, Color.VIOLET) -> Color.INDIGO
else -> throw Exception("Dirty color")
}
println(mix(Color.BLUE, Color.YELLOW))
- setOf()를 사용하여 순서와 관계없이 두 색상이 일치하는지 확인.
- 하지만 매번 새로운 Set 객체를 생성하므로 성능상 비효율적.
3.1 인자 없는 when 사용
불필요한 객체 생성을 줄이려면 when을 인자 없이 사용하면 된다.
fun mixOptimized(c1: Color, c2: Color) = when {
(c1 == Color.RED && c2 == Color.YELLOW) || (c1 == Color.YELLOW && c2 == Color.RED) -> Color.ORANGE
(c1 == Color.YELLOW && c2 == Color.BLUE) || (c1 == Color.BLUE && c2 == Color.YELLOW) -> Color.GREEN
(c1 == Color.BLUE && c2 == Color.VIOLET) || (c1 == Color.VIOLET && c2 == Color.BLUE) -> Color.INDIGO
else -> throw Exception("Dirty color")
}
- when에 인자를 전달하지 않고 Boolean 조건식으로 매칭.
- 객체 생성 없이 조건을 검사할 수 있어 성능이 향상됨.
4. 스마트 캐스트와 타입 검사
Kotlin에서는 is 연산자를 사용하여 객체의 타입을 검사할 수 있다.
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
4.1 if를 사용한 타입 검사
fun eval(e: Expr): Int {
if (e is Num) {
return e.value
}
if (e is Sum) {
return eval(e.right) + eval(e.left)
}
throw IllegalArgumentException("Unknown expression")
}
- is 연산자를 사용하여 객체가 특정 클래스의 인스턴스인지 검사.
- e as Num과 같이 명시적인 캐스팅이 필요 없음 (스마트 캐스트).
4.2 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")
}
- when을 사용하면 가독성이 향상됨.
4.3 블록 사용
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")
}
- 블록의 마지막 표현식이 결과값이 됨.
- 각 연산 과정을 출력하여 디버깅할 수도 있음.
5. 결론
- enum 클래스를 사용하면 값의 집합을 정의할 수 있으며, 프로퍼티와 메서드를 추가할 수 있음.
- when을 사용하면 switch보다 강력한 조건 분기를 구현 가능.
- 스마트 캐스트를 활용하면 불필요한 명시적 캐스팅을 줄일 수 있음.
- when을 인자 없이 사용하면 불필요한 객체 생성을 방지할 수 있음.
참고
- 드미트리 제메로프,스베트라나 이사코바, Kotlin in Action (에이콘출판, 2017)