목표
- enum class의 사용법을 이해한다.
enum class에 대한 함수 만들기
class Task {
var state: State = State.WAITING
fun printState() =
when(state){
State.WAITING -> println("Waiting..")
State.PROCESSING -> println("Processing..")
State.DONE -> println("Task done")
}
enum class State {
WAITING, PROCESSING, DONE
}
}
앞의 글에서 위의 코드를 보았다. 하지만, 이 코드는 문제가 있다. 특정한 state가 추가될 때마다 when의 분기에 무조건 print를 위한 처리 로직을 넣어주어야 한다.
공통 함수 만들기
우리는 enum class에 이러한 처리를 다음과 같이 함수(fun)으로 넣어줄 수 있다. 이렇게 만들면 변수에 따라 공통으로 처리된다.
class Task {
var state: State = State.WAITING
fun printState() = state.print()
enum class State {
WAITING, PROCESSING, DONE;
fun print() = println("${this}..")
}
}
fun main() {
val task = Task()
task.state = Task.State.WAITING
task.printState() // WAITING..
task.state = Task.State.PROCESSING
task.printState() // PROCESSING..
task.state = Task.State.DONE
task.printState() // DONE..
}
아래와 같이 printState를 했을 때 각자 공통으로 처리되어 보일러 플레이트 코드가 줄어든다. 하지만, 공통으로 처리할 때만 사용할 수 있으며 개별로 처리되어야 할 때는 추상 함수를 이용해야 한다.
추상 함수 만들기
추상 함수(abstract fun)가 선언되면, 모든 enum class의 종류별로 모두 추상 함수를 구현해야 한다. 이제 우리는 원래 결과값을 얻을 수 있게 되었다. 이러한 추상 함수를 사용하게 되면, 상수값에 대한 함수를 구현하는 것을 강제하므로 특정 상수값(enum)에 대한 처리를 빼먹는 것을 방지할 수 있다.
class Task {
var state: State = State.WAITING
fun printState() = state.print()
enum class State {
WAITING {
override fun print() {
println("Waiting..")
}
},
PROCESSING {
override fun print() {
println("Processing..")
}
},
DONE {
override fun print() {
println("Task Done")
}
};
abstract fun print()
}
}
fun main() {
val task = Task()
task.state = Task.State.WAITING
task.printState() // Waiting..
task.state = Task.State.PROCESSING
task.printState() // Processing..
task.state = Task.State.DONE
task.printState() // Task Done
}
enum class에 변수값 넣기
상수값과 연관된 변수를 해야하는 경우 상수값 외부에 선언하게 되면 관리가 어려워진다. 이를 위해서도 enum class를 사용할 수 있다.
예를 들어 색깔(Color)을 표현하는 함수를 표현한다고 해보자. 이러한 경우 RGB값이 필요하다. 이러한 RGB값을 상수값 외부에 선언한다고 해보자. 그렇다면 아래와 같이 선언할 수 있다.
class ColorState(R: Int, G: Int, B: Int)
val red = ColorState(255, 0, 0)
val green = ColorState(0, 255, 0)
val blue = ColorState(0, 0, 255)
이렇게 하면 반복되서 사용되는 변수라도 외부에다가 선언이 되어야 한다. 이렇게 된다면 관리 포인트가 여러개가 되게 된다.
enum class를 이용하면 다음과 같이 쓰면 된다. class선언부의 오른쪽에 상수가 가져야 하는 변수값을 선언한 다음 상수값에 연관된 변수를 상수 오른쪽에 저장할 수 있다.
enum class Color(R: Int, G: Int, B: Int) {
RED(255, 0, 0),
GREEN(0, 255, 0),
BLUE(0, 0, 255)
}
이렇게 되면 관리 포인트는 하나가 되어 변수 관리가 간편해진다.
enum class의 모든 변수 가져오기
enum class에 선언된 모든 상수값을 가져올 수도 있다. 우리는 이를 위해 enum class에 values 함수를 사용해서 Array형태로 가져올 수 있다.
enum class Color(R: Int, G: Int, B: Int) {
RED(255, 0, 0),
GREEN(0, 255, 0),
BLUE(0, 0, 255)
}
fun main() {
val colorArray: Array<Color> = Color.values()
colorArray.forEach {
println(it)
}
}
/* print값
RED
GREEN
BLUE
*/
위의 코드를 보면 Color의 Array를 Color.values()를 통해 가져올 수 있다.
정리
여러 곳에 같은 상수를 정의하거나 상수 외부에 상수와 관련된 변수나 함수를 정의하게 되면 코드가 커지면 커질 수록 관리가 어렵게 된다. enum class를 이용하면 상수값에 대한 관리 포인트를 일원화 할 수 있다. enum class를 적극적으로 활용하도록 하자.