Kotlin数据类拷贝方法不是深拷贝所有成员
有人可以解释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 = 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
也是一个副本。
要深入复制所有成员,我可以这样做:
val fooCopy = foo.copy(bar = foo.bar.copy(), list = foo.list.toMutableList())
fooCopy:Foo(a = 5,bar = Bar(x = 0),list = [1,2,3])
但是我是否错过了一些东西,还有没有更好的方法来做到这一点,而不需要指定这些成员需要强制复制?
Kotlin的copy
方法根本不应该是一个深层次的复制。 如参考文档( https://kotlinlang.org/docs/reference/data-classes.html )中所述,对于类如下:
data class User(val name: String = "", val age: Int = 0)
copy
实现将是:
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
所以你可以看到,这是一个浅的副本。 在你的具体情况下copy
的实现将是:
fun copy(a: Int = this.a, bar: Bar = this.bar, list: MutableList = this.list) = Foo(a, bar, list) fun copy(x: Int = this.x) = Bar(x)
正如@Ekeko所说,为数据类实现的默认copy()
函数是一个浅的副本,如下所示:
fun copy(a: Int = this.a, bar: Bar = this.bar, list: MutableList = this.list)
要执行深层复制,您必须覆盖copy()
函数。
fun copy(a: Int = this.a, bar: Bar = this.bar.copy(), list: MutableList = this.list.toList()) = Foo(a, bar, list)
- 添加Realm类后无法创建Android项目
- com.android.tools.build:gradle版本高于2.0.0时,无法在物理设备上运行/部署应用程序
- Dagger 2命名不能没有@Provides方法提供
- Login Activity示例中的checkParameterIsNotNull错误
- Android的 – 如何使用Kotlin在SortTableView中设置ColumnComparator
- 约束布局在布局文件中不可见…并获取错误,同时膨胀任何视图
- Android Kotlin不能在lambda中使用list.sort()
- 用Kotlin关闭/隐藏Android软键盘
- Kotlin和@Transient