数据类
本课属于 Coddy Kotlin 学习旅程的“面向对象编程”单元。第 32 课,共 57 课。
数据类是一种主要用于保存数据的类。data 修饰符会让编译器根据主构造函数的属性生成 toString()、equals()、hashCode()、copy() 和 componentN():
data class Point(val x: Int, val y: Int)在 main 中:
val a = Point(1, 2)
val b = Point(1, 2)
println(a)
println(a == b)
println(setOf(a, b).size)输出:
Point(x=1, y=2)
true
1如果没有 data,println 会显示类名和哈希码,例如 Point@1b6d3586,而两个值相同的对象并不相等。copy() 会创建一个更改了某些属性的新对象,并保留原对象不变,因此具有 val 属性的数据类可以作为不可变值使用:
data class User(val name: String, val email: String, val admin: Boolean = false)在 main 中:
val ada = User("Ada", "ada@example.com")
val boss = ada.copy(admin = true)
println(ada)
println(boss)
println(ada == boss)输出:
User(name=Ada, email=ada@example.com, admin=false)
User(name=Ada, email=ada@example.com, admin=true)
false解构声明会将对象解包为变量:val (x, y) = point 会按构造函数中的顺序调用生成的 component1() 和 component2()。它也适用于 for 循环和 lambda 参数,使用 _ 可以跳过一个属性:
data class Score(val player: String, val points: Int, val level: Int)在 main 中:
val scores = listOf(Score("ada", 120, 3), Score("bo", 95, 2))
for ((player, points) in scores) println("$player: $points")
val (_, bestPoints, bestLevel) = scores.maxBy { it.points }
println("best: $bestPoints at level $bestLevel")输出:
ada: 120
bo: 95
best: 120 at level 3只有主构造函数中的属性会参与其中:在类体中声明的属性不会包含在 toString、equals、hashCode 和 copy 中。数据类至少需要一个构造函数参数,并且每个参数都必须是 val 或 var:
data class Reading(val sensor: String, val value: Int) {
var note = ""
}在 main 中:
val r1 = Reading("t1", 20)
val r2 = Reading("t1", 20)
r1.note = "checked"
println(r1)
println(r1 == r2)输出:
Reading(sensor=t1, value=20)
true挑战
简单将 Book 设为 data class,这样打印和比较时会按值进行。然后完成三个函数:parse(line) 将 Dune;Herbert;1965 转换为 Book,newEdition(book, year) 返回一个副本,其中年份为新年份,标题中还添加了 (new edition),而 describe(book) 使用解构声明返回 Dune by Herbert, 1965。
提供的代码会解析每一行输入,打印每本书、重复项的数量、第一本书的新版本(年份为 2024),以及每本不同书的描述。
你的代码写在 Book.kt 和 BookTools.kt 中。Main.kt 存放提供的输入/输出代码,不能编辑。
亲手试试
fun main() {
// 提供的输入/输出代码:保持原样
val input = generateSequence(::readLine).toList()
val books = input.map { parse(it) }
for (b in books) println(b)
println("duplicates: ${books.size - books.distinct().size}")
println(newEdition(books[0], 2024))
for (b in books.distinct()) println(describe(b))
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Kotlin 在线编辑器