데이터 클래스 (Data classes)
코틀린의 데이터 클래스는 주로 데이터를 보유하는 데 사용되는 클래스입니다. 데이터 클래스는 자동으로 인스턴스를 가독성 있는 출력으로 표시하거나 인스턴스를 비교하고 복사하는 등의 추가 멤버 함수를 포함합니다. 데이터 클래스는 다음과 같이 'data'로 표시됩니다:
data class User(val name: String, val age: Int)
컴파일러는 주요 생성자에 선언된 모든 프로퍼티에서 다음 멤버들을 자동으로 생성합니다:
- .equals()/.hashCode() 쌍
- "User(name=John, age=42)"와 같은 형식의 .toString()
- 프로퍼티가 선언된 순서대로 해당 프로퍼티에 대응하는 .componentN()
- 함수.copy() 함수 (아래 참조)
생성된 코드의 일관성과 의미 있는 동작을 보장하기 위해 데이터 클래스는 다음 요구 사항을 충족해야 합니다:
- 주요 생성자는 최소한 하나의 매개변수를 가져야 합니다.
- 모든 주요 생성자 매개변수는 val 또는 var로 표시되어야 합니다.
- 데이터 클래스는 abstract, open, selaed, inner가 될 수 없습니다.
또한 데이터 클래스 멤버의 생성은 다음과 같은 규칙을 따릅니다:
- 데이터 클래스 본문에 .equals(), .hashCode(), .toString()의 명시적 구현이나 슈퍼클래스에서 최종 구현이 있는 경우, 이러한 함수가 생성되지 않고 기존의 구현이 사용됩니다.
- 슈퍼타입에 .componentN() 함수가 있고 이 함수가 열린 함수이며 호환 가능한 유형을 반환하는 경우, 해당 함수는 데이터 클래스에 대해 생성되며 슈퍼타입의 함수를 덮어씁니다. 슈퍼타입의 함수가 호환되지 않는 시그니처로 인해 덮어쓸 수 없거나 최종 함수인 경우, 오류가 보고됩니다.
- .componentN() 및 .copy() 함수에 대한 명시적 구현 제공은 허용되지 않습니다.
데이터 클래스는 다른 클래스를 확장할 수 있습니다 (예: sealed classes 참조).
JVM에서 생성된 클래스가 매개변수 없는 생성자를 가져야 하는 경우, 프로퍼티의 기본값을 지정해야 합니다 (생성자 참조).
예시:
data class User(val name: String = "", val age: Int = 0)
클래스 본문에 선언된 프로퍼티들 (Properties declared in the class body)
컴파일러는 자동으로 생성된 함수에 사용되는 것은 주요 생성자 내에서 정의된 프로퍼티만 사용합니다. 생성된 구현에서 특정 프로퍼티를 제외하려면 해당 프로퍼티를 클래스 본문 내에 선언하세요.
data class Person(val name: String) {
var age: Int = 0
}
이 예제에서는 .toString(), .equals(), .hashCode(), .copy() 구현 내에서는 이름 프로퍼티만 사용할 수 있으며, .component1() 함수도 하나뿐입니다. 나이 프로퍼티는 클래스 본문에 선언되었기 때문에 .toString(), .equals(), .hashCode(), .copy() 구현 내에서 사용할 수 없습니다. 이름은 같지만 나이가 다른 두 개의 Person 객체는 동일하게 취급됩니다. 이는 .equals() 함수가 이름 프로퍼티의 동등성만을 확인할 수 있기 때문입니다.
예:
val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20
println("person1 == person2: ${person1 == person2}")
// person1 == person2: true
println("person1 with age ${person1.age}: ${person1}")
// person1 with age 10: Person(name=John)
println("person2 with age ${person2.age}: ${person2}")
// person2 with age 20: Person(name=John)
복사 (Copying)
객체를 복사하려면 .copy() 함수를 사용하여 해당 객체의 일부 프로퍼티를 변경하고 나머지를 변경하지 않은 상태로 유지할 수 있습니다. 위의 User 클래스에 대한 이 함수의 구현은 다음과 같을 것입니다:
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
그럼 다음과 같이 작성할 수 있습니다:
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
데이터 클래스와 구조 분해 선언 (Data classes and destructuring declarations)
데이터 클래스에 대해 생성된 구성 요소 함수는 구조 분해 선언에서 사용할 수 있게 해줍니다:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age")
// Jane, 35 years of age
표준 데이터 클래스 (Standard data classes)
표준 라이브러리에서는 Pair와 Triple 클래스를 제공합니다. 그러나 대부분의 경우, 이름이 지정된 데이터 클래스가 더 나은 설계 선택지입니다. 왜냐하면 이러한 데이터 클래스는 프로퍼티에 의미 있는 이름을 제공하여 코드를 더 읽기 쉽게 만들어주기 때문입니다.
원문
'Kotlin' 카테고리의 다른 글
[Kotlin] data class가 애플리케이션 성능에 미치는 영향 (0) | 2023.08.27 |
---|---|
[Kotlin] Kotlin 공식 문서 번역 - 역호환성 (Backward compatibility) (0) | 2023.08.26 |
[Kotlin] Kotlin 공식 문서 번역 - 클래스 (Classes) (0) | 2023.08.26 |
[Kotlin] inline 사용법 (4) - crossinline 사용법 (1) | 2023.08.16 |
[Kotlin] inline 사용법 (3) - noinline 사용법 (0) | 2023.08.15 |
댓글