Cute Apple
본문 바로가기
개발/Kotlin

[Kotlin] Data class 와 copy()

by 미댕댕 2022. 8. 3.

Data class 란❓

 toString(), hashCode(), equals(), copy()메소드를 자동으로 만들어주는 클래스

var 로 선언한 파라미터의 경우에는 getter와 setter 자동 생성

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

 

특징

  • 기본 생성자에 1개 이상의 파라미터가 있어야 함
  • 기본 생성자의 파라미터가 val 또는 var 로 선언해야 함
  • 다른 클래스를 상속받을 수 없음 (슈퍼 클래스를 가질 수 없음)
  • 자동으로 생성한 메소드를 오버라이딩할 경우, 오버라이드 된 메소드 사용

 

copy()

copy() 메서드는 이름 그대로 클래스 주 생성자의 데이터를 그대로 복사해서 data class로 반환

fun Test() {
    val user1 = User("Kenneth", "brother", 30)
    val user2 = user1.copy(name = "scarlet")
    // D/user1: User(name=Kenneth, position=brother, age=30)
    // D/user2: User(name=scarlet, position=brother, age=30)
}

 

copy 를 쓰는 이유❓

 

data class의 프로퍼티는 var, val 둘 중 무엇으로 선언하든 상관없음

다만, 모든 프로퍼티를 읽기 전용(val)로 만들어서 data class를 불변 클래스로 만드는 것을 권장

 

1. HashMap 등의 컨테이너에 객체를 담는 경우 불변성이 필수적이다.
2. 불변 객체는 추론이 쉽다.
3. 다중스레드 프로그램의 경우, 객체의 값이 변하면 스레드간 동기화를 해야한다.
4. 객체를 메모리상에서 직접 바꾸는 것보다 복사본을 만드는 편이 더 낫다.

 

 

copy 는 얕은복사❓

data class의 copy는 deep copy하지 않기 때문에 아래와 같은 상황이 발생

data class User(val name: String, val age: Int, var friends: MutableList<String>) {
    var isSuperStar : Boolean = false
}

fun main() {
    val friends = mutableListOf("a1", "a2", "a3")
    
    val user1 = User("minsu", 10, friends)
    user1.isSuperStar = true
    
    val user2 = user1.copy()
    user2.friends.add("a4")

	//얕은 복사이기 때문에 user1의 친구 목록도 바뀌었다
    println(user1) // User(name=minsu, age=10, friends=[a1, a2, a3, a4])
    println(user2) // User(name=minsu, age=10, friends=[a1, a2, a3, a4])
}

 

해결방안

copy 메서드를 직접 구현

=>  copy 는 Any 의 메서드가 아니기 때문에 override 가 아닌 직접구현해주어야함

data class User(val name: String, val age: Int, var friends: MutableList<String>) {
    var isSuperStar : Boolean = false
    
    fun copy(): User {
        val copyUser = User(name, age, friends.toMutableList())
        copyUser.isSuperStar = isSuperStar
        
        return copyUser
    }
}

fun main() {
    val friends = mutableListOf("a1", "a2", "a3")
    
    val user1 = User("minsu", 10, friends)
    user1.isSuperStar = true
    
    val user2 = user1.copy()
    user2.friends.add("a4")

    println(user1) // User(name=minsu, age=10, friends=[a1, a2, a3])
    println(user2) // User(name=minsu, age=10, friends=[a1, a2, a3, a4])
    println(user1.isSuperStar) // true
    println(user2.isSuperStar) // true
}

 

 

 

 

== 와 === 의 차이

  • 값이 동일한지 체크
    • [Java] equals
    • [Kotlin] ==
  • 메모리상 동일한 객체인지 체크
    • [Java] ==
    • Kotlin] ===
class User (
    val name: String,
    val position: String,
    val age: Int
)

// val user1 = User("Kenneth", "brother", 30)
// val user2 = User("Kenneth", "brother", 30)

// user1==user2 true
// uesr1===user2 false

 

 

참고

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

https://velog.io/@dddooo9/Kotlin-data-class-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0-copy-toString-equals-hashcode-componentN

 

반응형

'개발 > Kotlin' 카테고리의 다른 글

[Kotlin] Serializable vs Parcelable  (0) 2022.09.07
[Kotlin] lateinit vs by lazy  (0) 2022.07.30
[Kotlin] Scope Function  (0) 2022.07.27
[Kotlin] 코틀린이란?  (0) 2022.07.25

댓글