본문 바로가기
Dev Log/Kotlin

Kotlin - Data Class 데이터 클래스 (공식문서 번역)

by 삽질하는큐 2020. 5. 2.

 

이 글은 Kotlin 공식 문서의 "Data Classes"를 번역한 글입니다. 다소 오역과 의역이 있을 수 있습니다.

https://kotlinlang.org/docs/reference/data-classes.html

 

Data Classes - Kotlin Programming Language

 

kotlinlang.org


우리는 자주 데이터를 가지고 있을 목적의 클래스를 생성합니다. 이러한 클래스에서 몇가지 표준적인 기능이나 유틸 함수 등은 바로 데이터를 통해서 유추가 됩니다. 코틀린에서는 이러한 클래스를 데이터 클래스 Data Class라고 칭하며 data 키워드를 앞에 붙입니다.

 

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

 

컴파일러는 primary constructor 에서 선언된 모든 프로퍼티에 대한 다음의 멤버들을 자동적으로 유추합니다.

 

  • equals() / hashCode()
  • toString() => User(name=John, age=42) 의 형태
  • 프로퍼티 선언 순서에 따라 생성되는 componentN() 함수
  • copy() 함수

일관성을 유지하고 생성된 코드가 의미 있게 하기 위해서 data class는 다음과 같은 사항을 지켜야 합니다.

  • primary constructor는 최소 하나 이상의 파라미터가 있어야 한다.
  • primary constructor의 모든 파라미터는 val 또는 var 키워드가 있어야 한다.
  • data class는 abstract, open, sealed, inner 클래스가 될 수 없다.
  • (코틀린 1.1 버전 이전까지) data class는 인터페이스 구현만 가능하다.

추가적으로 멤버의 상속과 관련한 규칙이 있기 때문에 멤버를 만들 때 다음과 같은 규칙을 따릅니다.

  • data class body 내에 equals(), hashCode(), toString()의 명시적이 구현이 있는 경우, 혹은 상위 클래스의 final 구현체가 있는 경우에, 해당 멤버는 생성되지 않고 구현체들이 사용된다.
  • 상위 타입에 open 키워드가 componentN() 함수가 있고 호환되는 리턴 타입이라면(compatible return types) 해당 함수는 데이터 클래스에 생성되어야 하고 상위 타입을 override 합니다. 호환되지 않는 시그니처 등으로 인해서 상위 타입의 함수가 override할 수 없거나, final로 지정되어 있다면 에러를 표시하게 됩니다.
  • 이미 copy() 함수가 있는 타입으로부터 해당 시그니처에 맞는 data class를 추론하는 것은 Kotlin 1.2에서 deprecated 되었고 1.3에서는 금지되었습니다.
  • 명시적으로 componentN() 과 copy() 함수를 구현할 수 없습니다.

1.1 버전부터 data class는 다른 class를 상속할 수 있습니다. (자세한 내용은 Sealed Class를 참고해주세요)

 

JVM 레벨에서 파라미터가 없는 생성자가 필요하다면, 모든 프로퍼티의 초깃값이 지정되어야 합니다. 

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

Class body 내에 선언된 프로퍼티

컴파일러가 자동 생성하는 함수들은 primary constructor 내에 정의된 프로퍼티만을 사용합니다. 자동 생성되는 함수에서 제외하고자 하면 class body 내에 선언하는 것이 좋습니다.

 

위에서 name 이라는 프로퍼티만 toString(), equals(), hashCode(), copy() 함수에서 사용되고, component함수는 component1()만 있을 것입니다. 아래 예제에서 두 Person 객체는 다르지만 동등하게 취급될 것입니다.

객체 복사하기

객체의 프로퍼티 중 일부는 바꾸고 나머지는 변하지 않은 채로 복사해야할 때가 있습니다. copy() 함수는 이러한 목적을 위해 생성됩니다. 위의 User 클래스에서 구현체는 다음과 같을 것입니다.

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

 

이렇게 되면 다음과 같은 코드를 쓸 수 있습니다.

data class와 구조 분해 선언

data class에서 component 함수들이 생성되어 구조 분해 선언이 가능합니다.

기본 데이터 클래스

코틀린에 내장된 Pair와 Triple이라는 data class가 있습니다. 하지만 많은 경우에 새로운 data class를 만드는 것이 설계상 더 좋을 것입니다. 프로퍼티에 의미 있는 이름을 주고 가독성을 높일 수 있기 때문입니다.