数据类
Kotlin 减少了重复性的编码工作
class 机制为您执行了大量的工作。然而,创建主要用于保存数据的类仍然需要大量重复的代码。当您需要一个基本上是数据持有者的类时,data 类简化了您的代码并执行常见的任务。
在 Kotlin 中,data 类简化了主要用于保存数据的类的代码,减少了重复性的编码工作。
您可以使用 data 关键字定义一个 data 类,告诉 Kotlin 生成额外的功能。每个构造函数参数前面必须加上 var 或 val:
// DataClasses/Simple.kt
package dataclasses
import atomictest.eq
data class Simple(
val arg1: String,
var arg2: Int
)
fun main() {
val s1 = Simple("Hi", 29)
val s2 = Simple("Hi", 29)
s1 eq "Simple(arg1=Hi, arg2=29)"
s1 eq s2
}
这个例子展示了 data 类的两个特点:
- 通过
s1产生的String与我们通常看到的不同;它包含对象所持有的参数名称和值的信息。data类以一种漂亮、可读的格式显示对象,而无需额外的代码。 - 如果您创建了两个包含相同数据(属性的相等值)的相同
data类的实例,您可能希望这两个实例也相等。对于普通类,要实现这种行为,您必须定义一个特殊的equals()函数来比较实例。在data类中,这个函数会自动生成;它会比较所有指定为构造函数参数的属性的值。
下面是一个普通类 Person 和一个 data 类 Contact 的例子:
// DataClasses/DataClasses.kt
package dataclasses
import atomictest.*
class Person(val name: String)
data class Contact(
val name: String,
val number: String
)
fun main() {
// 这两个看起来是相同的,但实际上不是:
Person("Cleo") neq Person("Cleo")
// data 类定义了合理的相等性:
Contact("Miffy", "1-234-567890") eq
Contact("Miffy", "1-234-567890")
}
/* 输出结果:
dataclasses.Person@54bedef2
Contact(name=Miffy, number=1-234-567890)
*/
因为 Person 类是没有使用 data 关键字定义的,所以包含相同 name 的两个实例并不相等。幸运的是,将 Contact 定义为 data 类会得到合理的结果。
请注意 data 类的显示格式与 Person 的区别,Person 只显示默认的对象信息。
对于每个 data 类,还生成了一个非常有用的函数 copy(),它创建一个包含当前对象数据的新对象。但是,它也允许您在此过程中更改选定的值:
// DataClasses/CopyDataClass.kt
package dataclasses
import atomictest.eq
data class DetailedContact(
val name: String,
val surname: String,
val number: String,
val address: String
)
fun main() {
val contact = DetailedContact(
"Miffy",
"Miller",
"1-234-567890",
"1600 Amphitheatre Parkway")
val newContact = contact.copy(
number = "098-765-4321",
address = "Brandschenkestrasse 110")
newContact eq DetailedContact(
"Miffy",
"Miller",
"098-765-4321",
"Brandschenkestrasse 110")
}
copy() 函数的参数名称与构造函数参数相同。所有参数都有默认值,等于当前值,因此您只需要提供要替换的参数的值。
HashMap 和 HashSet
创建一个 data 类还会生成适当的 哈希函数,以便对象可以用作 HashMap 和 HashSet 中的键:
// DataClasses/HashCode.kt
package dataclasses
import atomictest.eq
data class Key(val name: String, val id: Int)
fun main() {
val korvo: Key = Key("Korvo", 19)
korvo.hashCode() eq -2041757108
val map = HashMap<Key, String>()
map[korvo] = "Alien"
map[korvo] eq "Alien"
val set = HashSet<Key>()
set.add(korvo)
set.contains(korvo) eq true
}
hashCode() 与 equals() 结合使用,快速查找 HashMap 或 HashSet 中的 Key。手动创建正确的 hashCode() 是棘手且容易出错的,因此让 data 类为您完成这项工作非常有益。有关 equals() 和 hashCode() 的更多详细信息,请参阅运算符重载。
在 www.AtomicKotlin.com 上可以找到练习和解答。