[Kotlin] data class와 주의사항
데이타 클래스(data class)란
- Kotlin에서 데이터를 저장하는 목적으로 사용되는 특별한 종류의 클래스. 데이터 클래스는 일반 클래스와 달리 몇가지 유용한 기능을 자동으로 제공함.
데이타 클래스의 특징
간단한 선언:
data
키워드를 사용하여 쉽게 선언data class Person(val name: String, val age: Int)
자동 생성 메소드: 컴파일러가 아래의 메소드를 자동으로 생성
toString()
equals()
hashcode()
componentN()
함수들
불변성: 주 생성자의 파라미터를
val
로 선언하여 불변 객체를 만들 수 있음var
로 선언하는 경우 해시 기반 컬랙션에서 예상치 못한 동작이 발생할 수 있다.
Destructuring (구조분해): 데이터 클래스의 속성을 쉽게 분해할 수 있다.
val persion = Person("Alice", 30) val (name, age) = person
data class 사용 예시
data class User(val name: String, val id: Int)
fun main(){
val user1 = User("John", 1)
val user2 = User("John", 1)
println(user1) // User(name=John, id=1)
println(user1 == user2) //true
val user3 = user1.copy(name = "Jane")
println(user3) // User(name=Jane, id=1)
user1 == user2 에서 자동 생성된 equals method 가 사용 되는데, 이때 객체 비교를 메모리 주소로 하는것이 아니라 값을 기준으로한다.
data class의 제한 사항
- Primary Constructor(주 새성자)는 최소 하나의 파라미터를 가져야한다.
- 모든 Primary Constructor는
val
또는var
로 표시되어야한다. - data class는
abstract
,sealed
,inner
class가 될 수 없다.
data class가 자동 생성하는 메소드
toString()
- data class는 모든 프로퍼티를 포함하는 가독성 좋은 문자열 표현을 제공한다.
- Primary Constructor에 정의된 프로퍼티를 표시해준다.
- 필요하다면 override해서 사용할 수 있다.
data class User(val name:String, val age: 25)
val user1 = User("Alice", 25)
println(user1.toString())
// output: User(name=Alice, age=25)
hashCode()
- Primary Constructor에 정의된 모든 프로퍼티를 사용하여 해시코드를 계산한다.
- 필요한 경우 override해서 커스터 마이징 할 수 있다. 하지만 이 경우 equals() 메소드와의 일관성 유지가 필요하다.
val user1 = User("John", 1)
val user2 = User("John", 1)
val user3 = User("Alice", 2)
println(user1.hashCode()) // ex: 421124123
println(user2.hashCode()) // ex: 421124123 user1과 같은 값
println(user3.hashCode()) // ex: -127486178 user1과 다른 값
val userSet = hashSetOf(user1, user2, user3)
println(userSet.size) // 2 user1과 user2는 동일한 것으로 간주됨
equals()
- 구조적 동등성을 판단한다 : 객체의 내용을 비교하여 동등성을 판단한다. 모든 프로퍼티의 값이 같으면 동등하다고 간주한다.
- Primary Constructor에 정의된 모든 프로퍼티를 비교에 사용한다.
- type safe : 비교하는 객체의 타입을 먼저 확인한다.
- null safe : null에 대한 안전한 비교를 수행한다.
- hashCode()와 일관성: equals()가 true르 반환하는 두 객체는 반드시 같은 hashCode()를 가져야한다.
val person1 = Person("Alice", 30)
val person2 = Person("Alice", 30)
val person3 = Person("Bob", 25)
println(person1 == person2) // true
println(person1 == person3) // false
println(person1.equals(person2)) // true
println(person1.equals(person3)) // false
copy()
- 불변성 유지: 원본 객체를 변경하지 않고 새로운 객체를 생성.
- 선택적 파라미터: 변경하고자 하는 속성만 지정할 수 있음
- type safe: 컴파일시 타입체크가 이루어짐
- 모든 프로퍼티 복사 : 명시적으로 변경하지 않은 프로퍼티는 원본 객체의 값을 그대로 유지
data class Person(val name: String, val age: Int, val city: String)
val alice = Person("Alice", 30, "New York")
// 나이만 변경
val olderAlice = alice.copy(age = 31)
println(olderAlice) // Person(name=Alice, age=31, city=New York)
// 도시만 변경
val aliceInLondon = alice.copy(city = "London")
println(aliceInLondon) // Person(name=Alice, age=30, city=London)
// 여러 속성 변경
val bobInParis = alice.copy(name = "Bob", age = 25, city = "Paris")
println(bobInParis) // Person(name=Bob, age=25, city=Paris)
copy의 주의사항
copy():는 shallow copy를 수행한다. 중첩된 객체나 컬랙션은 참조만 복사된다.
복사를 너무 많이하면 성능에 악영향이 있을 수 있다.
변경되지 않은 값은 그대로 사용한다.
- 파라미터로 전달된 값만을 변경하고, 변경되지 않은 필드는 원본 객체 값을 그대로 사용한다.
- 이 방식으로 불필요한 객체 생성 작없을 회피한다.
data class User(val name: String, val age: Int) val user1 = User("Alice", 25) val user2 = user1.copy(age = 30) println(user1.name === user2.name) // true, name 필드는 그대로 재사용
data class LargeData(val id: Int, val name: String, val description: String) val large1 = LargeData(1, "Test", "This is a large data object.") val large2 = large1.copy(description = "Updated description.") println(large1.id === large2.id) // true, id 필드는 그대로 재사용 println(large1.name === large2.name) // true, name 필드도 그대로 재사용 println(large1.description === large2.description) // false, 변경된 description만 새로 생성
`* == 값 동등성 비교 / === 참조 동등성 비교
'웹프로그래밍 > Kotlin' 카테고리의 다른 글
[KOTLIN] CLASS (0) | 2023.02.25 |
---|---|
[코틀린 KOTLIN 정리]01.코틀린 시작하기 (0) | 2021.06.02 |
[코틀린KOTLIN 정리]0. 들어가며 (0) | 2021.06.02 |