| type | doc |
|---|---|
| layout | reference |
| category | Classes and Objects |
| title | Классы данных |
| url | https://kotlinlang.ru/docs/reference/data-classes.html |
Нередко мы создаём классы, единственным назначением которых является хранение данных. Функционал таких классов зависит от самих данных, которые в них хранятся. В Kotlin класс может быть отмечен словом data:
data class User(val name: String, val age: Int)Такой класс называется классом данных. Компилятор автоматически извлекает все члены данного класса из свойств, объявленных в первичном конструкторе:
- пара функций
equals()/hashCode(), toString()в форме"User(name=John, 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. Однако, в большинстве случаев, проименованные классы данных являются лучшим решением, потому что делают код более читаемым, избегая малосодержательные имена для свойств.