null

Интересные возможности data class в Kotlin

Начало

Данная статья больше посвящена для тех, кто недавно вошел в мир Kotlin, в ней я хотел бы рассмотреть data classes в языке Kotlin. Помимо определенных ограничений и некоторой области применения (хранение данных), data classes предоставляют определенный набор функциональных возможностей. Для начала мы кратко пройдемся по основному, а после разберем дополнительные преимущества data class.

Пробежка по базе

В первую очередь стоит отметить, что классы данных отличаются от обычных классов тем, что в data class генерируются дополнительные члены класса, а также накладываются определенные ограничения, связанные с их областью применения, а также с правилами генерации кода, такие как:

  • data class не могут быть абстрактными, open, sealed или inner
  • primary constructor должен иметь как минимум один параметр
  • все параметры primary constructor должны быть отмечены, как val или var

В обычном сценарии data class используют для генерации следующих членов класса, всеми знакомых из Java:

  • equals()
  • hashCode()
  • toString()

Всякое интересное

Помимо основных функций, которые обычно все генерировали в Java с помощью Lombok, data classes предоставляют также 2 другие, весьма интересные функции:

  • компонентные функции componentN()
  • copy()

Давайте разберем их подробнее:

Компонентные функции относятся к мульти-декларациям. Зачастую нам нужно достать поля из объекта и работать с ними по отдельности. В таком случае удобной была бы конструкция:

data class User(val email: String, val password: String)
...
val (email, password) = user
println(email)
println(password)

И Kotlin нам её предоставляет, автоматически генерируя компонентные функции в data classes, которые соответствуют свойствам, в соответствии с порядком их объявления.

Теперь же поговорим о функции copy(). Она нужна как можно догадаться по названию для копирования объектов класса. Различают 2 способа копирования, shallow copy и deep copy. Чем они отличаются мы разбирать в данной статье не будем, вы можете найти эту информацию в интернете. По умолчанию при вызове copy() у объекта будет выполнено shallow copy, однако, если вам нужно deep copy, вы можете это сделать с легкостью, переопределяя копирование лишь тех параметров, которые вам нужно скопировать по другому. К примеру:

data class User(val email: String, val password: String, val role: Role)
data class Role(val permission: String)
...
val userCopy = user.copy(
    role = user.role.copy()
)

Конец