본문 바로가기
개발새발/코틀린

[코틀린/Kotlin] enum / enum class

by 조희우 2025. 9. 8.

enum

  • 열거형; enumeration
  • 여러 개의 이름이 붙은 상수를 하나의 타입으로 묶어서 표현
  • 상수 값이 미리 정해져있고, 컴파일 시점에 확정

일반 enum

  • 상수 목록만 정의: 추가 메서드나 프로퍼티 없음
  • 각 상수는 고유한 값을 가짐
  • 보통 switch-case나 조건문에서 사용

Java에서의 enum

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

class Main {
    public static void main(String[] args) {
        Direction dir = Direction.NORTH;
        System.out.println(dir); // NORTH
    }
}
  • Direction 타입의 변수는 4개의 값 중 하나만 가짐

enum vs. 상수(final static)

// 기존 상수 정의 방식
public static final int NORTH = 0;
public static final int SOUTH = 1;

// enum 방식
enum Direction { NORTH, SOUTH }
  • final static: 타입 구분이 불가능
  • enum: 타입 강제 → 타입 안정성

Kotlin에서의 enum

  • enum class로 열거형을 생성
  • Java처럼 enum과 enum class를 구분하지 않음 → 모든 열거형이 사실상 클래스
enum class Direction {
	NORTH, SOUTH, EAST, WEST
}
  • Direction은 열거형이자 클래스로 생성자/메서드/프로퍼티도 가질 수 있음.

enum Class

  • 열거형 클래스; enumeration class
  • 상수 집합을 정의 할 때 사용
  • 각 상수는 해당 enum class 타입의 고유한 인스턴스
  • 상수명은 관례적으로 대문자로 표기
  • Kotlin에서는 모든 열거형이 enum class로 정의

기본 선언

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

fun main() {
	val dir = Direction.NORTH
	println(dir)             // NORTH
	println(dir.name)        // "NORTH"
	println(dir.ordinal)     // 0
}
  • name → 상수이름(String)
  • ordinal → 상수의 순서 (0부터 시작)

생성자 & 프로퍼티

  • enum은 생성자와 프로퍼티 소유 가능
enum class Day(val isWeekend: Boolean) {
    MONDAY(false),
    TUESDAY(false),
    WEDNESDAY(false),
    THURSDAY(false),
    FRIDAY(false),
    SATURDAY(true),
    SUNDAY(true)
}

fun main() {
	println(Day.SATURDAY.isWeekend) // true
}

메서드 포함

  • enum class 안에 메서드 정의 가능
  • 각 상수는 추상 메서드 구현 가능
enum class Operation {
	PLUS {
		override fun apply(a: Int, b: Int) = a + b
	},
	MINUS {
		override fun apply(a: Int, b: Int) = a - b
	};
    
	abstract fun apply(a: Int, b: Int): Int
}

fun main() {
	println(Operation.PLUS.apply(3, 4)) // 7
}

values() & valueOf()

  • Java 스타일의 정적메서드
  • enum 클래스 이름 뒤에 바로 호출
  • 컴파일 타임에 enum 클래스가 생성하는 메서드
enum class Direction {
	NORTH, SOUTH, EAST, WEST
}

fun main() {
	val dirs = Direction.values()
	println(dirs.joinToString()) // NORTH, SOUTH, EAST, WEST
	
	val east = Direction.valueOf("EAST")
	println(east) // EAST
}
  • values(): 모든 enum 상수를 배열로 반환
  • valueOf(”이름”): 해당 이름의 상수 반환

enumValues<T>() & enumValueOf<T>(name: String)

  • 제네릭 함수로 클래스 이름을 직접 쓰지 않고 사용 가능
  • T가 컴파일 시점에 enum 클래스여야한다는 제약이 있음
  • Kotlin의 리플렉션과 제네릭 기능 활용 가능
enum class Color { RED, GREEN, BLUE }

fun main() {
	val colors = enumValues<Color>()   
	println(colors.joinToString()) // [RED, GREEN, BLUE]
    
	val red = enumValueOf<Color>("RED") 
	println(red) // Color.RED
}
  • enumValues<T>() : 모든 상수 배열 반환
  • enumValueOf<T>(name: String) : 이름으로 상수 찾기

values(), valueOf(String), enumValues<T>(), enumValueOf<T>() 차이점

구분 호출 방식 특징 사용 위치
values() EnumClass.values() enum 클래스의 static 메서드 Java 스타일, 컴파일러 자동 생성
valueOf(String) EnumClass.valueOf("NAME") static 메서드, 이름으로 반환 Java 스타일
enumValues<T>() enumValues<EnumType>() 제네릭 함수, 타입 인자로 사용 Kotlin 표준 라이브러리
enumValueOf<T>() enumValueOf<EnumType>("NAME") 제네릭 함수, 이름으로 반환 Kotlin 표준 라이브러리

when 표현식 사용

  • when에서 enum을 사용 시 모든 값을 처리하면 else 사용 불필요
enum class Direction {
	NORTH, SOUTH, EAST, WEST
}

fun describe(dir: Direction) = when (dir) {
    Direction.NORTH -> "위쪽"
    Direction.SOUTH -> "아래쪽"
    Direction.EAST -> "오른쪽"
    Direction.WEST -> "왼쪽"
}

fun main() {
    val dir = Direction.NORTH
    println(describe(dir)) // 위쪽
}

enum calss vs. seald class

특징 enum class seald class
상수 개수 고정 (컴파일 시) 확장 가능(같은 파일)
인스턴스 미리 정의된 상수 각 하위 클래스가 별도 인스턴스
생성자 가질 수 있음 가질 수 있음
사용 예 방향, 요일, 상태값 상태 표현, 복합 데이터 타입

실습 문제

1. Enum↔String

Season enum을 보고 아래 조건에 맞추어 문제를 푸시오.

  • fromDisplayName 함수를 구현하여, 한글 표시 이름으로부터 Season을 찾아 반환하시오.
  • 없는 이름이 들어오면 null을 반환하시오.
enum class Season(val displayName: String) {
    SPRING("봄"),
    SUMMER("여름"),
    AUTUMN("가을"),
    WINTER("겨울");

    companion object {
        // TODO: fromDisplayName 구현
    }
}

fun main() {
    println(Season.fromDisplayName("봄")) // SPRING
    println(Season.fromDisplayName("가을")) // AUTUMN
    println(Season.fromDisplayName("장마")) // null
}

 

[힌트] enumValues<Season>() + find를 사용

 

 

답:

enum class Season(val displayName: String) {
    SPRING("봄"),
    SUMMER("여름"),
    AUTUMN("가을"),
    WINTER("겨울");

    companion object {
        fun fromDisplayName(name: String): Season? {
            return enumValues<Season>().find { it.displayName == name }
        }
    }
}

fun main() {
    println(Season.fromDisplayName("봄"))   // SPRING
    println(Season.fromDisplayName("가을")) // AUTUMN
    println(Season.fromDisplayName("장마")) // null
}

 

 

2. enum에 로직 포함하기

Operation enum은 두 숫자를 계산하는 기능을 수행해야한다.

각 상수에 대한 apply 메서드를 구현하시오.

enum class Operation {
    PLUS, MINUS, TIMES, DIVIDE;

    abstract fun apply(a: Int, b: Int): Int
}

fun main() {
    println(Operation.PLUS.apply(3, 5))  // 8
    println(Operation.DIVIDE.apply(10, 2)) // 5
}

 

[힌트] enum의 각 상수에 대해 익명 클래스처럼 오버라이드 가능

 

 

답:

enum class Operation {
	PLUS {
		override fun apply(a: Int, b: Int) = a + b
	},
	MINUS {
		override fun apply(a: Int, b: Int) = a - b
	},
	TIMES {
		override fun apply(a: Int, b: Int) = a * b
	},
	DIVIDE {
		override fun apply(a: Int, b: Int) = a / b
	};
	
	abstract fun apply(a: Int, b: Int): Int
}

fun main() {
    println(Operation.PLUS.apply(3, 5))  // 8
    println(Operation.DIVIDE.apply(10, 2)) // 5
}

 

 

 

3. Gson과 enum 변환

Status enum을 포함하는 데이터 클래스이다.

JSON으로 객체를 변환할 때 Status가 올바르게 매핑되도록 구현하시오.

import com.google.gson.Gson

enum class Status {
    ACTIVE, INACTIVE
}

data class User(val name: String, val status: Status)

fun main() {
    val json = """{"name":"홍길동","status":"ACTIVE"}"""
    // TODO: Gson으로 User 객체로 변환
}

[힌트] Gson이 기본적으로 enum 이름과 문자열 매핑 지원

 

 

답:

import com.google.gson.Gson

enum class Status {
    ACTIVE, INACTIVE
}

data class User(val name: String, val status: Status)

fun main() {
    val json = """{"name":"홍길동","status":"ACTIVE"}"""
    val user = Gson().fromJson(json, User::class.java)
    println(user)  // User(name=홍길동, status=ACTIVE)
}