Kotlin Weekly

Kotlin Weekly # -374 "얕은 복사 vs 깊은 복사"

베블렌 2023. 12. 4. 17:42

10월 1주차에는 Kotlin에서 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)의 차이점을 설명하고 있습니다. 이는 데이터 클래스와 리스트를 복사할 때 중요한 개념입니다.

 

https://blog.protein.tech/kotlin-shallow-vs-deep-copy-explained-907a72ccbf7a

 

Kotlin — Shallow vs Deep Copy Explained

In this article, I’ll explain the difference between deep and shallow copying in Kotlin and why it’s crucial to understand it when copying…

blog.protein.tech

 

 

소개

 

자바에서도 "=" 와 같이 리스트를 얕은 복사하는것과 for문을 돌면서 하나하나 세팅(?) 해주는 깊은 복사의 Kotlin에서의 이야기입니다. 이 글에서는 자바에서의 리스트 복사 방식과 유사한 방법을 Kotlin에서 사용하는 방법에 대해 설명합니다. 특히, Kotlin에서 데이터 클래스를 사용하여 리스트의 얕은 복사(Shallow Copy)와 깊은 복사(Deep Copy)를 수행하는 방법을 살펴보겠습니다.

 

 

내용

 

 

얕은 복사

 

  • 얕은 복사는 원본 객체의 새로운 복사본을 생성하지만, 중첩된 객체들의 새로운 복사본을 생성하지는 않습니다. 즉, 새 객체는 원본 객체와 동일한 중첩된 객체에 대한 참조를 가지게 됩니다.
  • Kotlin에서 데이터 클래스의 copy() 함수를 사용하여 얕은 복사를 할 수 있습니다.
  • 예를 들어, 사용자 객체를 복사한 후, 원본 사용자의 주소를 변경하면 복사된 사용자의 주소도 영향을 받습니다. 이는 copy() 함수가 중첩된 객체의 값을 복사하지 않고 참조만 할당하기 때문입니다.
data class Address(var city: String)

data class User(val name: String, val surname: String, val address: Address)

fun main() {
    val address = Address("New York")
    val originalUser = User("John", "Smith", address)
    val copiedUser = originalUser.copy(name = "Ilyas")

    println(originalUser) // User(name=John, surname=Smith, address=Address(city=New York))
    println(copiedUser) // User(name=Ilyas, surname=Smith, address=Address(city=New York))

    originalUser.address.city = "San Francisco"

    println(originalUser) // User(name=John, surname=Smith, address=Address(city=San Francisco))
    println(copiedUser) // User(name=Ilyas, surname=Smith, address=Address(city=San Francisco))
}

 

이 예제에서 originalUseraddress가 변경되면 copiedUseraddress도 같이 변경됩니다

 

 

 

깊은 복사

 

  • 깊은 복사는 원본 객체와 그 중첩된 모든 객체들의 복사본을 생성합니다. 따라서 원본 객체의 중첩된 객체에 변경이 발생해도 새로운 객체에는 영향을 미치지 않습니다.
  • Kotlin에서 깊은 복사를 구현하기 위해 Cloneable 인터페이스를 구현하고 사용자 정의 복사 메커니즘을 제공할 수 있습니다.
  • 깊은 복사를 수행하기 위한 또 다른 방법은 객체를 JSON으로 변환한 후 이를 사용하여 새 객체를 생성하는 것입니다.
data class Address(var city: String) {
    fun clone() = Address(city)
}

data class User(val name: String, val address: Address) {
    var isChanged = false

    fun clone(): User {
        val clonedAddress = this.address.clone()
        val clonedUser = User(this.name, clonedAddress)
        clonedUser.isChanged = this.isChanged
        return clonedUser
    }
}

fun main() {
    val address = Address("New York")
    val originalUser = User("John", address)
    originalUser.isChanged = true

    val clonedUser = originalUser.clone()
    originalUser.address.city = "San Francisco"

    println("Original: $originalUser, isChanged: ${originalUser.isChanged}")
    println("Cloned: $clonedUser, isChanged: ${clonedUser.isChanged}")
}

 

이 예제에서 originalUseraddress를 변경해도 clonedUser에는 영향을 주지 않습니다. clone() 메소드를 통해 깊은 복사가 이루어졌기 때문입니다.

 

 

리스트 복사

  • 모든 데이터 클래스의 속성이 불변이라면 toList() 또는 map { it.copy() }를 사용할 수 있습니다.
  • 변경 가능한 속성이 있는 경우 각 항목의 깊은 복사를 수행하는 clone() 메서드를 사용하여 복사할 수 있습니다.

 

 

정리

 

깊은 복사는 객체의 완전한 복제본을 생성하지만, 얕은 복사에 비해 느리고 더 많은 코드가 필요할 수 있습니다. 따라서, 가능하다면 불변 속성을 가진 데이터 클래스를 사용하는 것이 깊은 복사보다 권장됩니다.

 

 

 

 

 

http://kotlinweekly.net/

 

** Kotlin Weekly **

 

kotlinweekly.net