Kotlin 中文文档 v2.0.10 Help

数据类

Kotlin 中的数据类主要用于保存数据。 对于每个数据类,编译器会自动生成额外的成员函数,这些函数允许你将实例打印为可读输出、比较实例、复制实例等。 数据类使用 data 标记:

data class User(val name: String, val age: Int)

编译器会自动根据主构造函数中声明的属性生成以下成员:

  • .equals()/.hashCode() 对。

  • 形式为 "User(name=John, age=42)".toString()

  • .componentN() 函数 ,对应于属性的声明顺序。

  • .copy() 函数(见下文)。

为了确保生成的代码一致并且具有有意义的行为,数据类必须符合以下规定:

  • 主构造函数必须至少有一个参数。

  • 所有主构造函数的参数必须标记为 valvar

  • 数据类不能是抽象的、开放的、封闭的 或 内部的。

此外,关于数据类成员的生成,遵循以下继承规则:

  • 如果在数据类体内有明确实现 .equals().hashCode().toString() ,或者在超类中有final 实现,系统将不会自动生成这些函数,而是沿用已有的实现。

  • 如果超类型具有 open 且返回兼容类型的 .componentN() 函数,那么将为数据类生成相应的函数,并覆盖超类型的函数。 如果由于不兼容的签名或它们是最终实现而无法覆盖超类型的函数,则会报告错误。

  • 请勿为 .componentN().copy() 函数提供显式实现,这是不允许的。

数据类可以扩展其他类(参见密封类以获取示例)。

在类体中声明的属性

编译器只利用主构造函数内定义的属性来自动生成函数。若要排除某个属性不纳入生成的实现中,请将其声明在类体内:

data class Person(val name: String) { var age: Int = 0 }

在下面的示例中,只有 name 属性在 .toString().equals().hashCode().copy() 实现中被默认使用,并且只有一个组件函数 .component1()age 属性是在类体内部声明的,因此被排除在外。 因此,两个 Person 对象如果 name 相同但 age 值不同,它们会被认为是相等的,因为 .equals() 只评估来自主构造函数的属性:

data class Person(val name: String) { var age: Int = 0 } fun main() { //sampleStart val person1 = Person("John") val person2 = Person("John") person1.age = 10 person2.age = 20 println("person1 == person2: ${person1 == person2}") // person1 == person2: true println("person1 with age ${person1.age}: ${person1}") // person1 with age 10: Person(name=John) println("person2 with age ${person2.age}: ${person2}") // person2 with age 20: Person(name=John) //sampleEnd }

复制

使用 .copy() 函数复制一个对象,允许你在保持其余属性不变的情况下修改部分属性。 上面 User 类的此函数实现如下:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

之后,你可以这样写:

val jack = User(name = "Jack", age = 1) val olderJack = jack.copy(age = 2)

数据类和解构声明

为数据类生成的 组件函数 使它们可以在 解构声明 中使用:

val jane = User("Jane", 35) val (name, age) = jane println("$name, $age years of age") // Jane, 35 years of age

标准数据类

标准库提供了 PairTriple 类。 然而,在大多数情况下,命名的数据类是更好的设计选择,因为它们通过为属性提供有意义的名称,使代码更易读。

Last modified: 08 九月 2024