Kotlin Academy · 课时

使用 copy() 复制与部分覆盖

使用 copy() 创建修改后的实例,而不改变原始实例。

第 2 / 4 课13 个步骤

使用 copy() 复制与部分覆盖 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。

使用 copy() 进行不可变更新

copy() 会创建一个数据类的新实例,并修改其中的某些属性。未指定的属性会保留原始值。

基本 copy()

传入命名参数即可覆盖指定属性。
data class Person(val name: String, val age: Int, val city: String)
val alice = Person("Alice", 30, "Berlin")
val olderAlice = alice.copy(age = 31)
println(olderAlice)  // Person(name=Alice, age=31, city=Berlin)

复制多个字段

根据需要覆盖任意数量的字段。
data class Config(val host: String, val port: Int, val ssl: Boolean, val timeout: Int)
val prod = Config("prod.server", 443, true, 30)
val test = prod.copy(host = "test.server", port = 8080, ssl = false)
println(test)

copy 不会修改原对象

copy 始终会创建一个新对象,原对象完全不会改变。
data class Point(val x: Int, val y: Int)
val origin = Point(0, 0)
val moved = origin.copy(x = 5)
println(origin)  // Point(x=0, y=0) — unchanged
println(moved)   // Point(x=5, y=0)

深拷贝注意事项

copy 是浅拷贝。数据类中的可变对象会由原对象和副本共享。
data class Team(val name: String, val members: MutableList<String>)
val t1 = Team("A", mutableListOf("Alice"))
val t2 = t1.copy(name = "B")
t2.members.add("Bob")       // modifies SHARED list!
println(t1.members)  // [Alice, Bob] ← also changed!

避免浅拷贝问题

在数据类中使用不可变数据,以避免共享问题。
data class Team(val name: String, val members: List<String>)  // immutable list
val t1 = Team("A", listOf("Alice"))
val t2 = t1.copy(name = "B", members = t1.members + "Bob")
println(t1.members)  // [Alice]
println(t2.members)  // [Alice, Bob]

copy 在状态管理中的应用

在 Redux 风格或 MVI 架构中,copy 是更新状态的惯用方式。
data class UiState(val loading: Boolean, val items: List<String>, val error: String?)
fun reduce(state: UiState, action: Action) = when (action) {
    is Loading -> state.copy(loading = true)
    is Success -> state.copy(loading = false, items = action.data)
    is Error -> state.copy(loading = false, error = action.msg)
}

带默认参数的 copy

即使数据类包含许多属性,命名参数也能让 copy 依然易于使用。
data class Article(
    val id: Long, val title: String, val body: String,
    val published: Boolean = false, val views: Int = 0
)
val draft = Article(1L, "Hello", "Content...")
val published = draft.copy(published = true)
println(published.title)  // Hello

在测试中使用 copy

copy 让测试夹具更容易创建——先创建一个基础对象,再只修改所需的字段。
val baseUser = User(id = 1, name = "Test", email = "test@test.com", active = true)
val inactiveUser = baseUser.copy(active = false)
val renamed = baseUser.copy(name = "Renamed")

copy 与构建器模式

数据类的 copy() 是 Kotlin 对构建器模式的回应。对于包含许多可选字段的复杂对象,使用数据类加 copy 更简洁。
// Java Builder:
User.builder().name("A").age(30).role("admin").build()
// Kotlin:
val u = User("A", 30, "admin")  // or copy from base

记录语义

具有 val 属性的数据类表现得类似 Java 记录(JDK 16 及更高版本)——不可变、基于值,并且会自动转换为可打印形式。
data class RGB(val r: Int, val g: Int, val b: Int)
val white = RGB(255, 255, 255)
println(white)  // RGB(r=255, g=255, b=255)

快速检查

对数据类实例调用 copy() 后,原实例会发生什么?

回顾

copy() 会创建一个覆盖了指定字段的新实例,原实例保持不变。它非常适合状态管理、测试和构建器风格的构造。请注意可变属性带来的浅拷贝问题。下一步:解构!
免费开始

用 AI 导师学习 Kotlin — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
51
课程
203

常见问题解答

「使用 copy() 复制与部分覆盖」课时是免费的吗?

是的 — 「使用 copy() 复制与部分覆盖」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。

「使用 copy() 复制与部分覆盖」这节课中我会学到什么?

使用 copy() 创建修改后的实例,而不改变原始实例。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Kotlin Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 copy() 复制与部分覆盖」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Kotlin Academy 课中编写并运行代码吗?

能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 数据类基础:自动生成的方法
  2. 使用 copy() 复制与部分覆盖
  3. 使用 componentN 进行解构声明
  4. 集合中的数据类与作为 Map 键
← 返回 Kotlin Academy