Data Class
https://kotlinlang.org/docs/data-classes.html |
data class
Класс с единственным назначением - хранить данные. Компилятор автоматически добавляет в такой класс функции с определенной реализацией которая учитывает свойства класса определенные в первичном конструкторе.
• не может быть суперклассом, от data class
нельзя унаследоваться (из-за сложности кодогенерации).
• должен иметь как минимум один параметр val
или var
в первичном конструкторе.
• поля data-класса не учитываются при генерации методов, только поля из первичного конструктора (слишком накладно).
• не поддерживает модификаторы open
abstract
sealed
inner
.
• можно реализовывать интерфейсы и наследоваться от других open-классов. Если имена параметров совпадают в обоих классах их можно переопределить (должны быть также open
).
• если в суперклассе реализованы equals
hashCode
toString
- data class будет использовать их.
• стандартные реализации: Pair
Triple
.
• unlike java, не нужно указывать getters/setters.
• поддерживает декомпозицию на переменные с помощью функций componentN
.
Methods
equals
Сравнивает два объекта data-класса по значениям их полей, а не по ссылкам. Это удобно для проверки эквивалентности объектов.
data class Person(val name: String, val age: Int)
val person1 = Person("John", 30)
val person2 = Person("John", 30)
println(person1 == person2) // true, так как поля одинаковые
hashCode
Компилятор автоматически генерирует hashCode на основе значений всех свойств. Это важно для использования объектов в коллекциях, таких как HashMap или HashSet.
val personSet = hashSetOf(Person("John", 30))
println(personSet.contains(Person("John", 30))) // true
toString
Автоматически создаётся строковое представление объекта, которое выводит названия полей и их значения. Это упрощает отладку.
val person = Person("John", 30)
println(person) // Вывод: Person(name=John, age=30)
copy
Позволяет создавать копии объекта с возможностью изменения некоторых его полей.
val person1 = Person("John", 30)
val person2 = person1.copy(age = 31)
println(person2) // Вывод: Person(name=John, age=31)
componentN
Для каждого свойства генерируются методы доступа component1, component2, и т.д., которые позволяют использовать деструктуризацию.
val person = Person("John", 30)
val (name, age) = person // Деструктуризация
println(name) // John
println(age) // 30
Destructuring Declarations
Сопоставление с образцом позволяет легко извлекать и присваивать значения из объектов или коллекций нескольким переменным одновременно. Это удобный способ разбора сложных структур данных на отдельные компоненты.
data class Person(val name: String, val age: Int)
fun main() {
val person = Person("Alice", 30)
// Сопоставление с образцом
val (name, age) = person
println("Name: $name, Age: $age") // Выведет: Name: Alice, Age: 30
}
Kotlin Data Class. Вопросы на собесе
- Что такое data class в Kotlin и зачем он нужен?
- Как работают методы copy и componentN в data class?
- Как data-класс вычисляет хэшкод?
На основе всех полей, объявленных в первичном конструкторе класса. Используется метод
Objects.hash()
из Java.
- Что сделать чтобы поле не участвовало в вычислении хэшкода в data-классе?
Перенести его из первичного конструктора в тело data-класса или переопределить и переписать метод
hashCode()
.
- Как рекомендуется объявлять переменные в конструкторе data-класса?
Использовать
val
для неизменяемых полей (код более безопасный и предсказуемый).
- Перечисли методы data-класса?
equals()
hashCode()
toString()
сopy()
componentN()
- Kакие методы переопределены в data class?
equals()
hashCode()
toString()
- Можно ли наследоваться от data class?
Нет нельзя.
- Можно ли описать data-класс с пустым конструктором, но с полями внутри класса?
Нет нельзя.
- Как будут вычесляться методы если указать вторичный конструктор?
Если в data class указать вторичный конструктор, то методы equals, hashCode, toString, и copy будут по-прежнему вычисляться на основе свойств, объявленных в главном конструкторе, даже если вы добавите дополнительные конструкторы
- Какой из указанных модификаторов нельзя использовать с data-классом?
•
inner
•
open
•
abstract
• ни один из перечисленных
- Как нельзя объявлять data class?
•
data class MyClass(val a: Int)
•
open data class MyClass(val a: Int)
•
data class MyClass(val a: Int): Base()
•
data class MyClass()