[Kotlin] data class와 주의사항


데이타 클래스(data class)란

  • Kotlin에서 데이터를 저장하는 목적으로 사용되는 특별한 종류의 클래스. 데이터 클래스는 일반 클래스와 달리 몇가지 유용한 기능을 자동으로 제공함.

데이타 클래스의 특징

  1. 간단한 선언: data 키워드를 사용하여 쉽게 선언

    data class Person(val name: String, val age: Int) 
  2. 자동 생성 메소드: 컴파일러가 아래의 메소드를 자동으로 생성

    • toString()
    • equals()
    • hashcode()
    • componentN() 함수들
  3. 불변성: 주 생성자의 파라미터를 val로 선언하여 불변 객체를 만들 수 있음

    • var로 선언하는 경우 해시 기반 컬랙션에서 예상치 못한 동작이 발생할 수 있다.
  4. 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

+ Recent posts