Destructuring declarations (деструктуризация) в Kotlin позволяют "распаковывать" объекты на составные части прямо в объявлении переменных, что делает код более понятным и компактным.
Стандартно деструктуризация работает с data class и поддерживается для коллекций (через компонентные функции). Она основана на использовании функций componentN() внутри объекта класса.
Пример с data class:
data class User(val name: String, val age: Int) val user = User("Олег", 32) val (name, age) = user println(name) // "Олег" println(age) // 32
Пример для пользовательского класса:
class Point(val x: Int, val y: Int) { operator fun component1() = x operator fun component2() = y } val point = Point(1, 2) val (a, b) = point
Особенности и тонкости:
Вопрос: "Можно ли воспользоваться деструктуризацией для класса, не являющегося data class, и какие условия для этого необходимы?"
Ответ: Да, можно. Для этого необходимо вручную определить операторы componentN внутри класса. Data class их генерирует автоматически, но любой класс может их предоставить явно.
Пример:
class Pair<A, B>(val first: A, val second: B) { operator fun component1() = first operator fun component2() = second } val p = Pair(1, "q") val (a, b) = p
История
В проекте использовали деструктуризацию с Map и ошибочно предполагали, что деструктуризация доступна для любых итерируемых коллекций. В результате возникали ошибки "ComponentN is missing" для List, где предполагался не один компонент (а один), что приводило к крашу приложения.
История
В одном модуле деструктуризация применялась к пользовательским классам, но после рефакторинга забыли добавить operator-функции componentN, вследствие чего код компилировался, но вылетал при исполнении с NoSuchMethodError, остановив прод-работу сервиса.
История
Data class был модифицирован - атрибуты переставили местами, но при этом старые деструктурирующие объявления оставили без изменений. Итог — данные подставлялись в неправильные переменные, приводя к серьёзной бизнес-логике ошибке на проде.