有人能解释一下Kotlin数据类的copy方法到底是如何工作的吗?对于一些成员来说,似乎实际上并没有创建(深)副本,并且引用仍然是对原件的引用.

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)

输出:
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)

为什么是barCopy.x=0(预计),但fooCopy.bar.x=2(我认为应该是0).由于Bar也是一个数据类,所以当执行foo.copy()时,我希望foo.bar也是一个副本.

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?

推荐答案

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)

copy项实施将是:

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

正如你所见,这是一个肤浅的副本.在您的具体 case 中,copy的实现将是:

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)

Kotlin相关问答推荐

在intellij中使用kotlin符号和floordiv

某些公共函数显然不能在类实例上访问;Klaxon示例

使用另一个对象的列表创建对象

Spring Boot 3:为Kotlin中的TestRestTemplate配置读取超时

S使用MAP和ElseThrow的习惯用法是什么?

仅某些用户出现 DateTimeFormatter 错误

kotlin 父类具有依赖于抽象变量的变量

Lets plot Kotlin中的多轴比例

如何从 var list 或可变列表中获取列表流

Mixin 在 Jackson 中添加 defaultImpl 不起作用

是什么让 Kotlin 中的 String 类能够使用方括号?

listOf() 返回 MutableList

有没有办法重用 Job 实例?

如何使 TextInputEditText 只读?

如何修复 ViewPager2 中的Design assumption violated错误?

无法在 kotlin android 中以编程方式禁用 EditText

任何处理器都无法识别以下选项:'[kapt.kotlin.generated, room.incremental]'

kotlin中的全局可拓函数

将字符串编码为Kotlin中的UTF-8

如何在 IntelliJ IDEA 中禁用粘贴时将 Java 转换为 Kotlin?