# 数据类
我们经常要创建一个类,不做什么事只存储数据。在这样的类中一些标准的函数一般可机械地从数据中推导出来。在 Kotlin 中,有一种称为 _data class_ 的,标记为 `data`:
``` kotlin
data class User(val name: String, val age: Int)
```
编译器自动从主构造器中所声明的全部属性衍生出下列成员:
* 一组 `equals()`/`hashCode()`
* `“User(name=John, age=42)”` 形式的 `toString()`
* 与属性声明顺序一致的 [`componentN()` 函数](multi-declarations.html)
* `copy()` 函数(下面说明)
如果在类体中明确地定义或是从基类继承了这些函数其中的某些,它将不会被创建。
要确定生成的是有意义的代码,数据类必须满足下列必备条件:
* 主构造器需要至少一个形参;
* 所有的主构造器形参都要标记为 `val` 或 `var`;
* 数据类不能为 `abstract`、`open`、`sealed` 或 `inner`;
* (1.1 版之前)只能实现接口。
从版本 1.1 开始,数据类可以扩展其它类
在 JVM 上,如果生成的类需要有一个无参构造器,那么所有的属性都得指定默认值(查看[构造器](classes.md#constructors))
``` kotlin
data class User(val name: String = "", val age: Int = 0)
```
## 复制
我们经常遇到需要复制一个对象,变更它的一些属性,但保留其余未改变的情况。这就是 `copy()` 产生的目的。对于上面的 `User` 类,它的实现应该像下面这样:
``` kotlin
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
```
这样就允许我们这么写
``` kotlin
val jack = User(name = "Jack", age = 1)
val olderJack = jack.copy(age = 2)
```
## 数据类和析构声明
_Component 函数_ 的生成是为了数据类能启用它们的[析构声明](multi-declarations.html):
``` kotlin
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
```
## 标准数据类
标准库提供了 `Pair` 和 `Triple`。大多数情况下,想一下,命名数据类是一个更好的选择方案,因为它们通过为属性提供有意义的名称让代码更可读。