조용한 담장

코틀린(Kotlin) 클래스(Class) : 열거 클래스 (Enum classes) 본문

kotlin

코틀린(Kotlin) 클래스(Class) : 열거 클래스 (Enum classes)

iosroid 2019. 12. 31. 18:24

코틀린의 열거 클래스(enum class) 에 대해 살펴보자.

원문 https://kotlinlang.org/docs/reference/enum-classes.html 을 보며 정리.

enum 타입의 클래스 이다.

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

내부의 각각의 상수(constant)들은 오브젝트이다.

Initialization

각각의 enum 은 enum class 의 인스턴스 이므로 특정 값으로 초기화 될 수 있다.

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

fun main() {
    println(Direction.NORTH.toString())
    println(Color.RED.rgb.toString(16))
}

// output:
// NORTH
// ff0000

Anonymous Classes

enum constant 는 자신의 anonymous class 들과 method 들을 선언할 수 있고 base method 를 override 할 수 있다.

enum class ProtocolState {
    WAITING {
        override fun signal() = TALKING
    },

    TALKING {
        override fun signal() = WAITING
    };

    abstract fun signal(): ProtocolState
}

enum class 에 멤버를 정의할때는, ; 으로 멤버 정의와 enum constant 정의를 구분해야 한다.

Enum 의 항목(entry)들은 중첩된 클래스를 가질 수 없다.

Implementing Interfaces in Enum Classes

enum class 는 상속 대신 interface 를 사용하게 된다.

interface 는 모든 항목을 위한 하나의 인터페이스 멤버를 가지거나 anonymous class 안에 있는 각각의 항목을 위한 인터페이스들을 가진다.

import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator

enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
    PLUS {
        override fun apply(t: Int, u: Int): Int = t + u
    },
    TIMES {
        override fun apply(t: Int, u: Int): Int = t * u
    };

    override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}

fun main() {
    val a = 13
    val b = 31
    for (f in IntArithmetics.values()) {
        println("$f($a, $b) = ${f.apply(a, b)}")
    }
}

// output:
// PLUS(13, 31) = 44
// TIMES(13, 31) = 403

Working with Enum Constants

Enum class 는 정의된 enum constant 를 리스트화 할수 있고 이름으로 enum constant 를 얻을 수 있는 synthetic methods 를 가진다.

이런 methods 의 signature 는 아래와 같다.

// EnumClass is the name of enum class
EnumClass.valueOf(value: String): EnumClass
EnumClass.values(): Array<EnumClass>

println(Direction.valueOf("NORTH"))
println(Direction.values().joinToString())

// output:
// NORTH
// NORTH, SOUTH, WEST, EAST

valueOf() 는 일치하는 enum constant 가 없으면 IllegalArgumentException 를 발생시킨다.

enumValues<T>(), enumValueOf<T>() 함수를 통해 generic 방식으로 enum class 의 constant 에 접근할 수 있다.

enum class RGB { RED, GREEN, BLUE }

inline fun <reified T : Enum<T>> printAllValues() {
    print(enumValues<T>().joinToString { it.name })
}

printAllValues<RGB>() // prints RED, GREEN, BLUE

모든 enum constant 는 enum 정의내에서의 자신의 이름과 위치를 얻을 수 있는 property 를 가진다.

val name: String
val ordinal: Int

println(Direction.SOUTH.name) // SOUTH
println(Direction.SOUTH.ordinal) // 1

enum class 내에서 정의된 순서대로 comparable interface 를 통해 enum constant 의 순서가 처리된다.

if (Direction.NORTH < Direction.SOUTH) {
    println("NORTH < SOUTH")
}

 

Comments