Объекты данных в Kotlin

Андрей Шагин
NOP::Nuances of Programming
3 min readApr 25, 2023

Объекты данных — это новый функционал, представленный в Kotlin 1.7.20 и планируемый к выпуску в версии 1.9. Разберемся, для чего он нужен.

Какую проблему призваны решить объекты данных?

Ниже, в типичном примере иерархии запечатанных классов, используется sealed interface (мог быть и sealed class), которым определяются возможные состояния экрана профиля: data class для состояния успеха, а object для состояний ошибки и загрузки.

sealed interface ProfileScreenState {
data class Success(val username: String): ProfileScreenState
object Error: ProfileScreenState
object Loading: ProfileScreenState
}

А что если нужно занести в журнал или распечатать текущее состояние экрана для отладки либо отправки в службу аналитики? В строковом представлении класса данных ProfileScreenState.Success как раз содержатся имя класса и все его свойства.

Но если в Kotlin вывести обычное объявление object, получим строку с полным именем пакета, именем объекта и адресом, где этот объект хранится в памяти. Поскольку объекты в Kotlin — синглтоны, при каждом выводе этого объекта адресная часть останется неизменной и для нас нерелевантной:

com.dataobjects.example.ProfileScreenState$Loading@6d03e736
Success(username=exampleUser1)
com.dataobjects.example.ProfileScreenState$Error@5fd0d5ae

Одно из решений — на каждом объекте реализации переопределить функцию toString(): String:

sealed interface ProfileScreenState {
data class Success(val username: String) : ProfileScreenState

object Error : ProfileScreenState {
override fun toString(): String = "Error"
}

object Loading : ProfileScreenState {
override fun toString(): String = "Loading"
}
}

Не слишком ли много шаблонного кода для такой тривиальной задачи?

Объекты данных

В Kotlin эту проблему планируют решить с помощью объектов данных. data object — это обычный object, но с реализацией по умолчанию функции toString(), которая выводит его имя без ручного ее переопределения и с соответствием поведения определению data class. Соответствие поведения классам данных особенно актуально для иерархий запечатанных классов.

Сейчас объекты данных — это экспериментальный функционал. Чтобы его опробовать, указываем компилятору версию Kotlin 1.9:

kotlinOptions.languageVersion = "1.9"

Синхронизировав проект, получаем в имеющихся объектах — части запечатанной иерархии — предложение преобразовать их в data object:

Предложение интегрированной среды разработки — преобразовать в объект данных запечатанный подобъект
Предложение интегрированной среды разработки — преобразовать в объект данных объект с переопределенной функцией toString

После применения предложения объекты преобразуются в data object:

sealed interface ProfileScreenState {
data class Success(val username: String) : ProfileScreenState
data object Error : ProfileScreenState
data object Loading : ProfileScreenState
}

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

Loading
Success(username=exampleUser1)
Error

Заключение

Объекты данных — это новый функционал Kotlin, который улучшает строковое представление object. Он особенно актуален, когда имеются иерархии запечатанных классов с другими классами данных и их нужно занести в журнал или распечатать для отладки или аналитики.

Обратите внимание: на момент написания этой статьи объекты данных — экспериментальный функционал Kotlin. В будущем их определение может измениться.

Подробнее об объектах данных Kotlin см. в:

Читайте также:

Читайте нас в Telegram, VK и Дзен

Перевод статьи Domen Lanišnik: Data Objects in Kotlin

--

--