Kotlin v2.0.21 Help

数据类

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

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

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

  • equals()/hashCode() 配对。

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

  • 与声明顺序对应的 componentN() 函数

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

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

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

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

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

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

  • 如果在数据类的主体中有 equals()hashCode()toString() 的显式实现,或者在超类中有 final 实现,则这些函数不会被生成,现有的实现将被使用。

  • 如果超类型具有 opencomponentN() 函数并且返回兼容类型,则为数据类生成相应的函数,并重写超类型中的函数。 如果由于签名不兼容或函数为 final ,无法重写超类型的函数,则会报告错误。

  • 不允许为 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: 26 十一月 2024