Дорогие читатели,
Помогите сделать документацию лучше!

К сожалению текст все еще содержит некоторое количество ошибок, и мы просим вас найти и исправить их. Если бы каждый из посетителей исправил хотя бы одну ошибку, то мы смогли бы довести до совершенства весь материал всего за один день.


Классы данных

Нередко мы создаём классы, единственным назначением которых является хранение данных. Функционал таких классов зависит от самих данных, которые в них хранятся. В Kotlin класс может быть отмечен словом data:

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

Такой класс называется классом данных. Компилятор автоматически извлекает все члены данного класса из свойств, объявленных в первичном конструкторе:

  • пара функций equals()/hashCode(),
  • toString() в форме "User(name=Jhon, age=42)",
  • функции componentN(), которые соответствуют свойствам, в зависимости от их порядка либо объявления,
  • функция copy() (см. ниже)

Если какая-либо из этих функций явно определена в теле класса (или унаследована от родительского класса), то генерироваться она не будет.

Для того, чтобы поведение генерируемого кода соответствовало здравому смыслу, классы данных должны быть оформлены с соблюдением некоторых требований:

  • Первичный конструктор должен иметь как минимум один параметр;
  • Все параметры первичного конструктора должны быть отмечены, как val или var;
  • Классы данных не могут быть абстрактными, open, sealed или inner;
  • Дата-классы не могут наследоваться от других классов (но могут реализовывать интерфейсы).

Начиная с версии 1.1, классы данных могут расширять другие классы (см. примеры в Sealed classes)

Для того, чтобы у сгенерированного в JVM класса был конструктор без параметров, значения всех свойств должны быть заданы по умолчанию (см. Конструкторы)

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

Копирование

Довольно часто нам приходится копировать объект с изменением только некоторых его свойств. Для этой задачи генерируется функция 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"

Стандартные классы данных

Стандартная библиотека предоставляет Pair и Triple. Однако, в большинстве случаев, проименованные классы данных являются лучшим решением, потому что делают код более читаемым, избегая малосодержательные имена для свойств.

Статья на эту тему на Хабре