Классы данных
#
Васильев Андрей Михайлович, 2024
Версии презентации
Создание классов данных
#
Нередко мы создаём классы, единственным назначением которых является хранение данных
Функционал и некоторые служебные функции таких классов зависят от самих данных,
которые в них хранятся. В 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
- Классы данных могут наследовать другие классы и реализовывать интерфейсы
Свойства, объявленные в теле класса
#
Компилятор использует только свойства, определенные в основном конструкторе для
автоматически созданных функций. Чтобы исключить свойство из автоматически
созданной реализации, объявите его в теле класса:
data class Person(val name: String) {
var age: Int = 0
}
Только свойство name будет учитываться в реализациях функций toString()
,
equals()
, hashCode()
и copy()
, и будет создана только одна компонентная функция
component1()
. Даже если два объекта класса Person будут иметь разные значения
свойств age, они будут считаться равными.
val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20
Классы данных и мульти-декларации
#
Сгенерированные для классов данных компонентные функции позволяют использовать
их в мульти-декларациях
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // выводит "Jane, 35 years of age"
Копирование
#
Используйте функцию 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)
Копирование при записи
#
Благодаря функции copy()
классы данных позволяют простым образом обрабатывать
данные внутри приложения. Каждое новое состояние записывается в отдельный объект
- Как это происходит с числами
- Как это происходит со строками в Java
val initial = User(
name = "Василий",
age = 5,
)
val daysPassed = initial.copy(
age = 55,
)
Чем больше полей в классе данных, тем эффективнее операция копирования при
записи