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. Вопросы на собесе
  1. Что такое data class в Kotlin и зачем он нужен?
  1. Как работают методы copy и componentN в data class?
  1. Как data-класс вычисляет хэшкод?

    На основе всех полей, объявленных в первичном конструкторе класса. Используется метод Objects.hash() из Java.

  1. Что сделать чтобы поле не участвовало в вычислении хэшкода в data-классе?

    Перенести его из первичного конструктора в тело data-класса или переопределить и переписать метод hashCode().

  1. Как рекомендуется объявлять переменные в конструкторе data-класса?

    Использовать val для неизменяемых полей (код более безопасный и предсказуемый).

  1. Перечисли методы data-класса?

    equals() hashCode() toString() сopy() componentN()

  1. Kакие методы переопределены в data class?

    equals() hashCode() toString()

  1. Можно ли наследоваться от data class?

    Нет нельзя.

  1. Можно ли описать data-класс с пустым конструктором, но с полями внутри класса?

    Нет нельзя.

  1. Как будут вычесляться методы если указать вторичный конструктор?

    Если в data class указать вторичный конструктор, то методы equals, hashCode, toString, и copy будут по-прежнему вычисляться на основе свойств, объявленных в главном конструкторе, даже если вы добавите дополнительные конструкторы

  1. Какой из указанных модификаторов нельзя использовать с data-классом?

    inner

    open

    abstract

    ни один из перечисленных

  1. Как нельзя объявлять 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()