본문 바로가기
Language/Kotlin

[Kotlin] Enum Class & Data Class

by 진꿈청 2024. 9. 3.

Kotlin

 

데이터 클래스

일반적으로 레이어간 데이터 전달을 위해 `DTO`라는 객체를 생성하여 사용한다.

 

`Kotlin`에서는 이러한 역할을 수행할 수 있는 데이터 클래스를 제공하는데

데이터 클래스를 사용하면 아래와 같은 메소드를 자동으로 생성해준다.

  • equals
  • getter/setter
  • hashCode
  • toString
  • copy
  • componentN

 

`Kotlin`에서 데이터 클래스는 아래와 같은 형식으로 정의할 수 있다.

data class DataClassSample(val name: String, val age: Int)

 

클래스 앞에 `data` 키워드를 붙여 정의한다.

 

 

열거형 클래스

우리는 `Enum` 클래스를 사용하여 일정 범주 안에 들어갈 수 있는 상수들을 묶어 관리할 수 있다.

 

`Enum` 클래스를 사용하는 이유

  • 코드가 단순해지고, 가독성이 좋아짐
  • 인스턴스의 생성과 상속 등을 방지하고 타입 안정성을 보장함

 

`Enum` 클래스는 아래와 같이 구현할 수 있다.

enum class Color(val label: String, val code: String){
    RED("red", "#FE2E2E"),
    YELLOW("yellow", "#F7FE2E"),
    GREEN("green", "#40FF00"),
    BLUE("blue", "#0000FF");
}

 

이렇게 선언된 클래스는 아래와 같이 활용할 수 있다.

val red = Color.RED
println(red)
pritnln(red.label)
println(red.code)

 

이 외에도 각 타입마다 함수를 구현하여 기능을 동작하게 할 수 있다.

 

 

실습

데이터 클래스

package dataclass

data class DataClassSample(val name: String, val age: Int)
class NoDataClassSample(val name: String, val age: Int)

fun main() {
    val data1 = NoDataClassSample(name = "flature", age = 10)
    val data2 = NoDataClassSample(name = "flature", age = 10)

    println(data1.hashCode())
    println(data2.hashCode())

    println(data1 == data2) // false
    println(data1.toString())

    val data3 = DataClassSample(name = "flature", age = 10)
    val data4 = DataClassSample(name = "flature", age = 10)

    println(data3.hashCode())
    println(data4.hashCode())

    println(data3 == data4) // true
    println(data3.toString())
    println("name is ${data3.component1()}")
    println("age is ${data3.component2()}")

    val (name, age) = data3
    println(name)
    println(age)

    val data5 = data3.copy()
    val data6 = data3.copy(name = "around hub studio")

    println(data3 == data5)
    println(data5 == data6)
    println(data5)
    println(data6)
}

 

`DataClassSample`과 `NoDataClassSample` 클래스를 생성하였다.

 

코드의 내용을 살펴보면 `NoDataClassSample`의 경우 필드에 같은 값을 갖는 두 객체를 생성하였을 때,

그 두 객체의 `hashCode`를 출력해보면 값이 다르게 나온다. 또한 `==`으로 비교하였을 때 `false`가 나오게 된다.

 

마찬가지로, `toString()`에 의해 출력을 했을 때도 필드의 값의 나열이 아닌 -> `dataclass.NoDataClassSample@4a574795` 이런 값이 나오게 된다.

 

하지만, `DataClassSample`의 경우 필드가 같은 두 객체는 `hashCode`가 같게 나오며 `==` 연산에서도 `true`가 나온다.

또한, `toString()`으로 인한 출력에서도 `DataClassSample(name=flature, age=10)` 다음과 같이 나온다.

 

그리고 내부 함수로 아까 설명한 `componentN()`도 제공하는데 각 필드에 순서대로 접근할 수 있다.

 

다음으로, `Kotlin`은 `Python`과 같이 `val (name, age) = data3` 구조 분해를 제공한다.

 

마지막으로, `copy()`는 해당 객체를 복사하는 것으로 `data3 == data5`는 `true`가 나오게 된다.

이때 `data6`처럼 copy시 특정 필드의 값을 변경할 수 있고 그에 따라 `==` 비교 연산을 하면 `false`가 나오게 된다.

 

 

 Enum 클래스

package enums

enum class Color(val label: String, val code: String) {
    RED("red", "#FE2E2E"),
    YELLOW("yellow", "#F7FE2E"),
    GREEN("green", "#40FF00"),
    BLUE("blue", "#0000FF");
}

enum class HttpStatus(val label: String, val code: Int) {
    REDIRECT("redirect", 300) {
        override fun isServerError(): Boolean {
            return false
        }
    },
    BAD_REQUEST("bad request", 400) {
        override fun isServerError(): Boolean {
            return false
        }
    },
    INTERNAL_ERROR("internal error", 500) {
        override fun isServerError(): Boolean {
            return true
        }
    };

    abstract fun isServerError(): Boolean
}

enum class HttpStatus2(val label: String, val code: Int) : CheckStatus {
    REDIRECT("redirect", 300) {
        override fun isServerError(): Boolean {
            return false
        }
    },
    BAD_REQUEST("bad request", 400) {
        override fun isServerError(): Boolean {
            return false
        }
    },
    INTERNAL_ERROR("internal error", 500) {
        override fun isServerError(): Boolean {
            return true
        }
    };
}

interface CheckStatus {
    fun isServerError(): Boolean
}

fun main() {
    val red = Color.RED
    println(red)
    println(red.label)
    println(red.code)

    println()

    println("[[ color code list ]]")
    for (temp in Color.values()) {
        println("${temp.label} is ${temp.code}")
    }

    println()

    println(HttpStatus.BAD_REQUEST)
    println(HttpStatus.BAD_REQUEST.label)
    println(HttpStatus.BAD_REQUEST.code)

    println()

    println(HttpStatus.BAD_REQUEST.isServerError())
    println(HttpStatus.INTERNAL_ERROR.isServerError())

    println(HttpStatus2.BAD_REQUEST.isServerError())
    println(HttpStatus2.INTERNAL_ERROR.isServerError())
}

 

주요하게 알아볼 것은 `Java`처럼 `Color.values()`를 하게 되면 해당 `Enum` 클래스의 상수값들의 나열을 볼 수 있다.

 

앞서 설명한 것처럼 타입마다 함수를 구현하는 것이 가능한데

`HttpStatus` 클래스처럼 클래스 내부에 `abstract` 함수를 두어 구현하는 방법과

`HttpStatus2` 클래스처럼 새롭게 그냥 인터페이스를 만들어 `HttpStatus2` 클래스가 구현하는 방법이 있다.

'Language > Kotlin' 카테고리의 다른 글

[Kotlin] 상속  (1) 2024.09.03
[Kotlin] 클래스  (0) 2024.09.02
[Kotlin] 함수  (0) 2024.09.02
[Kotlin] 조건문과 반복문  (0) 2024.09.02
[Kotlin] 연산자  (0) 2024.09.02