数据类
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 上可以找到练习和解答。