如何写一个简单的数据存储类?
除了存储信息,类还应该能够比较对象、复制对象,并且方便地输出数据。通常,为了实现这些功能,类需要定义以下几个方法:
-
equals() 和 hashCode() —— 用于对象比较和在集合中正确工作。
-
copy() —— 用于复制对象,创建一个带有部分修改的新对象。
-
toString() —— 用于打印对象的字符串表示,方便调试。
-
componentN() 函数 —— 用于解构声明,按属性声明顺序一一对应。
但是在 Kotlin 中,你不需要自己写这些方法,只要用 data class
关键字就可以自动帮你实现。
Data class 示例
我们先定义一个普通类:
class Client(val name: String, val age: Int, val gender: String)
这个类有 3 个属性。为了比较两个对象是否相等(根据属性值),你通常需要重写 equals()
和 hashCode()
方法:
class Client(val name: String, val age: Int, val gender: String) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Client
if (name != other.name) return false
if (age != other.age) return false
if (gender != other.gender) return false
return true
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + age
result = 31 * result + gender.hashCode()
return result
}
}
这段代码很长,而且都是“标准模板”,非常重复且容易出错。
用 data class 简化
有了 data
关键字,Kotlin 会自动帮你生成这些代码:
data class Client(val name: String, val age: Int, val gender: String)
这样就足够了,equals()
、hashCode()
、toString()
、copy()
和 componentN()
都自动生成。
注意事项
- 只有主构造函数中的属性会参与自动生成的函数:
data class Client(val name: String, val age: Int, val gender: String) {
var balance: Int = 0
}
这里 balance
不在主构造函数中,所以不会参与 equals()
、hashCode()
等函数。
- 可以覆盖自动生成的方法,但不能覆盖
copy()
方法:
data class Client(val name: String, val age: Int, val gender: String) {
var balance: Int = 0
override fun toString(): String {
return "Client(name='$name', age=$age, gender='$gender', balance=$balance)"
}
}
这样 toString()
里也会显示 balance
字段。
- 主构造函数必须至少有一个参数,且所有参数必须是
val
或var
。
copy() 和 componentN() 函数
Kotlin 中复制对象很方便:
fun main() {
val bob = Client("Bob", 29, "Male")
val john = bob.copy(name = "John")
println(bob)
println(john)
}
输出:
Client(name=Bob, age=29, gender=Male)
Client(name=John, age=29, gender=Male)
这时,john
是 bob
的副本,只改了名字。
componentN()
函数允许你按顺序访问属性:
fun main() {
val bob = Client("Bob", 29, "Male")
println(bob.component1()) // Bob
println(bob.component2()) // 29
println(bob.component3()) // Male
// 解构声明
val (name, age, gender) = bob
println(name) // Bob
println(age) // 29
println(gender) // Male
}
小结
-
data class
是 Kotlin 用来简化存储数据的类的一个非常方便的关键字。 -
自动帮你生成比较、复制、打印和解构相关的函数,极大减少模板代码。
-
适合用于数据传输对象(DTO)和简单的值对象。
-
只要记住主构造函数里声明的属性才参与自动生成的逻辑。
-
用得好可以省时省力,让代码更简洁。