본문 바로가기
프로그래밍/Kotlin

[Kotlin] Data Class 이해하기

by tempus 2022. 5. 23.
반응형

 

Data Class는 보통 네트워크 통신이나 DB 모델을 만들 때 주로 사용합니다. 오늘은 이 Data Class가 무엇이고 일반적인 Class랑 무슨 차이가 있는지 알아보겠습니다.

 

Data Class란?

데이터 클래스는 데이터를 보관하기 위해 만들어진 클래스입니다. 데이터 클래스는 toString(), hashCode(), equals(), copy()메소드를 자동적으로 만들어줍니다.

 

아래와 같이 정의할 수 있습니다.

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

 

Data Class 특징

⑴ 데이터 클래스의 생성자는 1개 이상의 프로퍼티를 선언해야 한다.

⑵ 데이터 클래스 앞에 abstract, open, sealed, inner를 붙일 수 없다.

⑶ 데이터 클래스 생성자 프로퍼티는 val 또는 var로 선언해야 한다.

⑷ 데이터 클래스는 상속받을 수 없다.

⑸ 데이터 클래스에서 toString(),hashCode(), equals(), copy()를 override하면, 그 함수는 직접 구현된 코드를 사용한다.

 

Data Class의 메소드들

🟦 copy()

copy()는 객체의 복사본을 만들어 리턴합니다. 리턴되는 객체는 얕은 복사(swallow copy)로 생성됩니다. 주로 단순 필드 값만 변경하여 추가적으로 사용하고 싶을 때 유용합니다.

fun copyObject(){
    val food1 = Food("라면", 3000)
    val food2 = food1.copy(name = "김밥")
}

단, 여기서 copy()에서 사용할 수 있는 매개변수는 data class에 정의되어 있어야 합니다.

 

🟦 toString(), hashCode(), equals()

fun main(args: Array<String>) = with(Scanner(System.`in`)) {

    val food1 = Food("라면", 3000)
    val food2 = Food("김밥", 3000)

    //food1 : Food(name=라면, price=3000)	
	//food2 : Food(name=김밥, price=3000)
	
    //tohashCode()
	//food1 : 46622784
	//food2 : 44364403

}

toString()은 생성자에 정의된 프로퍼티만 출력합니다.

 

equals()같은 경우는 두 객체의 값이 동일한지 체크합니다. 만약 메모리상 동일한지 체크하고 싶으면 ===을 사용해야 합니다.

fun main(args: Array<String>) = with(Scanner(System.`in`)) {

        val food1 = Food("라면", 3000)
        val food2 = Food( "라면", 3000)

        println(food1 == food2) //true
        println(food1 === food2) //false
        println(food1.equals(food2)) //true

}

 

데이터 분해와 대입(Destructuring Declarations)

일반적으로 Data class로 생성한 객체의 내부 변수를 다른 변수에 대입하려면 다음과 같이 사용해야 합니다.

fun main(args: Array<String>) = with(Scanner(System.`in`)) {

        val food1 = Food("라면", 3000)

        val name = food1.name
        val price = food1.price
        
}

하지만 데이터 클래스는 Destructuring Declarations를 지원하기 때문에, 아래 코드처럼 한 줄로 표현이 가능합니다.

fun main(args: Array<String>) = with(Scanner(System.`in`)) {
    
        val food1 = Food("라면", 3000)
        val (name, price) = food1
}

만약 필요하지 않은 변수라면 다음과 같이 가져오면 됩니다.

fun main(args: Array<String>) = with(Scanner(System.`in`)) {
    
        val food1 = Food("라면", 3000)
        val (_, price) = food1
}

내부를 들여다 보면 데이터 클래스로 객체를 생성할 때 componentN()메소드를 생성합니다. 즉 Destructuring Declarations은 컴파일 시점에서 componentN()메소드를 자동 생성하며, 선언한 변수에 리턴 값을 넣어주도록 변환합니다.

 

그리고 데이터 클래스의 정의된 프로퍼티 순서대로 변수들에 대입되기 때문에 주의해야 합니다.

 

결론

이렇게 데이터 클래스는 일반 클래스보다 데이터를 보관하기 유용하고 다루기 편리합니다. DB 모델이나 네트워크 통신을 위한 모델을 만들 때는 데이터 클래스를 사용합시다!

 

 

Reference

 

반응형

댓글


loading