2018 Kotlin中的model

数据类

我们经常创建主要用于保存数据的类。在这样的类中,一些标准功能和效用函数通常可以从数据中机械地导出。在Kotlin中,这称为数据类,标记为data:

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

编译器自动从主构造函数中声明的所有属性派生以下成员:

equals()/ hashCode()pair;
toString()形式”User(name=John, age=42)”;
componentN()功能对应于在其声明的顺序的属性;
copy() 功能(见下文)。

为确保生成的代码的一致性和有意义的行为,数据类必须满足以下要求:

  • 主构造函数需要至少有一个参数;
  • 所有主要构造函数参数都需要标记为val或var;
  • 数据类不能是抽象的,开放的,密封的或内部的;
  • (1.1之前)数据类只能实现接口。

此外,成员生成遵循以下有关成员继承的规则:
- 如果存在显式实现equals(),hashCode()或者toString()在超类中的数据类主体 或 最终实现中,则不生成这些函数,并且使用现有实现;
- 如果超类型具有打开的componentN()函数并返回兼容类型,则会为数据类生成相应的函数,并覆盖超类型的函数。如果由于签名不兼容或最终导致超类型的功能无法覆盖,则会报告错误;
- 从已具有copy(…)匹配签名的函数的类型派生数据类在Kotlin 1.2中已弃用,并将在Kotlin 1.3中禁止。
- 不允许为componentN()和copy()函数提供显式实现。

从1.1开始,数据类可以扩展其他类(例如,参见密封类)。

在JVM上,如果生成的类需要具有无参数构造函数,则必须指定所有属性的默认值(请参阅构造函数)。

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

在类主体中声明的属性

请注意,编译器仅使用主构造函数中定义的属性来自动生成函数。要从生成的实现中排除属性,请在类主体中声明它:

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

只有财产name将在内部使用toString(),equals(),hashCode(),和copy()实现,并且只会有一个组件的功能component1()。虽然两个Person物体可以有不同的年龄,但它们将被视为相等。

val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20

仿形

通常情况下,我们需要复制一个改变其某些属性的对象,但保持其余的不变。这是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") // prints "Jane, 35 years of age"

标准数据类

标准库提供Pair和Triple。但是,在大多数情况下,命名数据类是更好的设计选择,因为它们通过为属性提供有意义的名称使代码更具可读性。

猜你喜欢

转载自blog.csdn.net/Sqq_yj/article/details/81538236