Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin data class copy method not deep copying all members

Could someone explain how exactly the copy method for Kotlin data classes work? It seems like for some members, a (deep) copy is not actually created and the references are still to the original.

fun test() {     val bar = Bar(0)     val foo = Foo(5, bar, mutableListOf(1, 2, 3))     println("foo    : $foo")      val barCopy = bar.copy()     val fooCopy = foo.copy()     foo.a = 10     bar.x = 2     foo.list.add(4)      println("foo    : $foo")     println("fooCopy: $fooCopy")     println("barCopy: $barCopy") }  data class Foo(var a: Int,                val bar: Bar,                val list: MutableList<Int> = mutableListOf())  data class Bar(var x: Int = 0) 

Output:
foo : Foo(a=5, bar=Bar(x=0), list=[1, 2, 3])
foo : Foo(a=10, bar=Bar(x=2), list=[1, 2, 3, 4])
fooCopy: Foo(a=5, bar=Bar(x=2), list=[1, 2, 3, 4])
barCopy: Bar(x=0)

Why is barCopy.x=0 (expected), but fooCopy.bar.x=2 (I would think it would be 0). Since Bar is also a data class, I would expect foo.bar to also be a copy when foo.copy() is executed.

To deep copy all members, I can do something like this:

val fooCopy = foo.copy(bar = foo.bar.copy(), list = foo.list.toMutableList()) 

fooCopy: Foo(a=5, bar=Bar(x=0), list=[1, 2, 3])

But am I missing something or is there a better way to do this without needing to specify that these members need to force a deep copy?

like image 302
triad Avatar asked Nov 17 '17 21:11

triad


People also ask

Is Kotlin copy a deep copy?

1) Copy() The copy() function is not a deep copy or a clone function. It makes a shallow copy of class. It is used in the case where we need to copy an object altering some of its properties, but keeping the rest unchanged.

What is shallow copy Kotlin?

This article explores different ways to clone an array in Kotlin. The solution should create a shallow copy of the array, i.e., the new array can reference the same elements as the source array. If the array contains any reference elements, they are copied as well.

How does copy work in Kotlin?

Kotlin makes working with immutable data objects easier by automatically generating a copy() function for all the data classes. You can use the copy() function to copy an existing object into a new object and modify some of the properties while keeping the existing object unchanged.


1 Answers

The copy method of Kotlin is not supposed to be a deep copy at all. As explained in the reference doc (https://kotlinlang.org/docs/reference/data-classes.html), for a class such as:

data class User(val name: String = "", val age: Int = 0) 

the copy implementation would be:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age) 

So as you can see, it's a shallow copy. The implementations of copy in your specific cases would be:

fun copy(a: Int = this.a, bar: Bar = this.bar, list: MutableList<Int> = this.list) = Foo(a, bar, list)  fun copy(x: Int = this.x) = Bar(x) 
like image 91
Ekeko Avatar answered Sep 17 '22 02:09

Ekeko