История вопроса:
До Kotlin 1.9 object-объекты не могли быть data — вы не могли иметь синглтон, автоматически получающий equals, hashCode, toString, как data-классы. С появлением data object это ограничение снято. Теперь можно создать singleton-объект с авто-генерированными методами, пригодный для паттернов Value и Enum-like.
Проблема:
Ранее для получения корректного equals(), hashCode(), toString() даже у singleton-объектов приходилось вручную их реализовывать или использовать другие финты, что увеличивало BOILERPLATE и возможность ошибки.
Решение:
Используйте data object для объектов, чей инстанс уникален, и при этом необходимо стандартное поведение equals/hashCode/toString для передачи в коллекции, сериализации, сравнения и дебага.
Пример кода:
data object NotAvailable fun checkStatus(status: Any) = when (status) { NotAvailable -> "Data is missing" else -> "Other status" } val set = setOf(NotAvailable) println(NotAvailable in set) // true println(NotAvailable.toString()) // NotAvailable
Ключевые особенности:
Могут ли data object содержать свойства?
Могут, но только val-свойства без backing field (т.к. ничего хранимого у singleton быть не должно)
data object Loading { val status: String get() = "Loading..." }
Чем data object отличается от обычного object с точки зрения equals?
Equals у обычного object проверяет только ссылочную идентичность, у data object сравнивается контракт data, но в случае singleton это всегда тот же объект. Однако, переопределённый equals/hashCode полезнее для коллекций.
Можно ли сделать наследование от data object?
Нет, data object финален, как и любой object в Kotlin — наследоваться нельзя.
Вместо enum для всех состояний использовали разные data object. Через год понадобилась сериализация по строкам, стали вручную сопоставлять имена объектов с типами.
Плюсы:
Минусы:
Для возвращаемого значения сетевого запроса использовали data object для специальных статусов: Loading, Empty, Error. Так код компактен, поддержка equals, hashCode, toString автоматом.
Плюсы:
Минусы: