Что такое data class в Kotlin и какие у него особенности
Что проверяют
Вопрос про Kotlin у тестировщика означает, что вы читаете код разработчиков и пишете автотесты на том же языке. Проверяют не заученное определение, а понимание того, что именно генерирует компилятор: от этого зависит поведение ассертов сравнения и коллекций в ваших тестах.
Как отвечать
data class нужен для объектов, которые переносят данные. Компилятор сам генерирует equals, hashCode, toString, copy и функции componentN для деструктуризации.
Главное ограничение: в генерацию попадают только свойства первичного конструктора. Требования к объявлению: хотя бы один параметр, каждый помечен val или var, класс получается финальным, унаследоваться от него нельзя.
data class User(val id: Int, val name: String) {
var role: String = "guest" // в equals и toString не попадёт
}Польза для тестов прямая: ожидаемый ответ сервиса сравнивается с фактическим одним assertEquals, а не десятком проверок полей; при падении toString показывает обе структуры целиком; copy собирает вариации фикстуры от одного базового объекта.
Где спотыкаются
Называют data class неизменяемым по умолчанию. Неизменяемость даёт val, а не ключевое слово data: var в конструкторе разрешён. Плюс copy делает поверхностную копию, и вложенный изменяемый список останется общим у оригинала и копии.
Забывают про границу первичного конструктора. Поле, объявленное в теле класса, в равенство не входит, и тест на двух объектах с разными значениями такого поля пройдёт зелёным. Деструктуризация же позиционная: перестановка полей в конструкторе молча меняет смысл строки val (a, b) = user.
Сравнивают объекты с массивами внутри. Сгенерированный equals зовёт equals у поля, а у массива это сравнение ссылок, поэтому два одинаковых набора байт окажутся неравными, нужен contentEquals и свой equals. Рядом живёт вторая ловушка: изменяемый объект положили в HashSet, поменяли поле, и он в множестве больше не находится.