공부/Kotlin

데이터 클래스 (Data Class)

bongcheonjy 2025. 4. 26. 17:52

데이터 클래스는 toString(), hashCode(), equals(), copy()등의 메소드를 자동으로 만들어주는 클래스이다.

기본적으로 데이터 클래스는 

1. 상속받을 수 없다.

데이터 클래스는 기본적으로 '값'을 다루는 단순한 객체를 만들기위함이다. 상속구조를 만들게 되면 단순 데이터라는 의도가 깨지게 되어 Kotlin에서는 이를 final class로 만들어 상속불가를 강제했다.

 

2. val 또는 var로 선언해야 한다.

1번과 비슷하다. 데이터 클래스는 데이터를 보관하는 목적이다. 메서드나 동작 중심이 프로퍼티(property) 중심으로, 프로퍼티로 정의해야한다. 따라서 읽기 전용이면 val, 변경 가능한 경우 var로 선언한다.

 

3. abstract, open, sealed, inner를 붙일 수 없다.

abstract : 데이터 클래스를 추상으로 만들면 구현되지않은 데이터 객체가 된다. 한마디로 말이안된다.

open : 데이터 클래스는 상속이 불가능하기 때문에 open을 허용하지 않는다.

sealed : sealed class는 계층 구조를 표현하기 위함이다. 데이터 클래스는 데이터를 나타내기 위함으로 쓸일이 없다.

inner : 데이터 클래스는 독립적이어야한다. 외부 클래스에 종속되게 만들면 독립성이 깨지기때문에 금지한다.

 

4. 1개 이상의 프로퍼티를 가지고 있어야한다.

데이터 클래스는 데이터를 담는 클래스로 프로퍼티가 아예 없으면 비어있는 데이터 객체가 되어버린다. 데이터를 저장할 의도가 없다면 그냥 object나 class를 쓰면 된다.

 

 

 

5. equals(), toString(), hashCode()에 Override 구현 시 구현 함수를 사용한다.

위 메서드들은 데이터 클래스를 만들면 자동으로 생성된다. 그런대 필요시 이를 직접 override 할 수도 있다. 이 경우 Kotlin은 사용자가 직접 작성한 코드를 무조건 따른다.

 

라는 5가지 특징을 가지고 있다.

 

그리고 데이터 클래스를 생성시 자동으로 생성되는 메서드들은 다음과 같은 역할을 한다.

1. equals()

기본 클래스는 참조(메모리 주소)를 비교하지만 데이터 클래스는 값으로 비교한다. 

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

val u1 = User("Alice", 20)
val u2 = User("Alice", 20)

위와 같은 경우 u1 == u2는 일반 클래스라면 false지만 데이터 클래스에선 값을 기준으로 비교하기 때문에 true가 나온다.

 

2.hashCode()

객체를 HashSet, HashMap에 넣을때 쓰는 고유번호를 자동으로 생성해준다. 즉 equals()가 같으면 hashCode()도 같아야 하는 규칙을 Kotlin이 자동으로 지켜준다.

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

val user1 = User("A",10)
val user2 = User("A",10)

위와 같은 경우 user1과 user2의 hashCode는 다르다.  일반 클래스의 경우 hashCode()가 Object.hashCode()를 따르기 때문이다

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

val user1 = User("A",10)
val user2 = User("A",10)

하지만 이 경우 user1과 user2의 hashCode는 동일하게 나온다 컴파일러가 프로퍼티를 모두 고려해서 hashCode를 생성하기 때문이다.

 

3.toString()

객체를 문자열로 출력해준다 클래스명과 프로퍼티명, 값을 자동으로 출력한다

val user = User("Alice", 20)
println(user)

이 경우 User(name=Alice, age=20)처럼 출력된다.

 

4.copy()

객체를 복사할때 사용한다. 기존 객체를 기반으로 일부 값만 바꿔서 새로운 객체를 만들 수 있다.

val user1 = User("Alice", 20)
val user2 = u1.copy(age = 25)

이 경우 user1은 그대로고 user2는 age만 25로 바뀐 User(name=Alice, age=25)로 바뀐 복제본이 된다.

 

5. componentN()

객체를 구조 분해 할 수 있게 해준다. 데이터 클래스의 프로퍼티들을 순서대로 추출 할 수 있다.

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

이런 데이터 클래스가 있다면 컴파일 할때 Kotlin은 자동으로 

fun component1(): String = name
fun component2(): Int = age

와 같은 함수를 생성한다. 이러한 함수들을 통해 객체를 변수 여러개로 풀어 쓸 수 있게된다.

 

아래 예시를 보자.

val user = User("Alice", 20)

val (name, age) = user

여기서 val (name, age) = user 구문이 자동으로 내부에서 

val name = user.component1()
val age = user.component2()

이런식으로 변환되어 

println(name) // Alice
println(age)  // 20

변수로 바로 사용가능하게 되는것이다.

 

'공부 > Kotlin' 카테고리의 다른 글

Kotlin 컬렉션  (0) 2025.04.26