Data Class
https://kotlinlang.org/docs/data-classes.html |
data class
Специальный тип класса, который упрощает создание классов для хранения данных. Они автоматически предоставляют множество полезных функций, что делает их идеальными для использования в качестве контейнеров для данных.
• Не может быть суперклассом, от data
-класса нельзя унаследоваться.
• Должен содержать хотя бы одно поле val
или var
в главном конструкторе.
• При генерации методов учитываются только поля из первичного конструктора.
• Не поддерживает модификаторы open
abstract
sealed
inner
.
• Могут реализовывать интерфейсы и наследоваться от обычных классов (если имена параметров совпадают в обоих классах их нужно переопределить).
• Если в суперклассе реализованы equals
hashCode
toString
- data
-класс будет использовать их.
• Поддерживает декомпозицию на переменные с помощью функций 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
https://kotlinlang.org/docs/destructuring-declarations.html |
Сопоставление с образцом позволяет легко извлекать и присваивать значения из объектов или коллекций нескольким переменным одновременно. Это удобный способ разбора сложных структур данных на отдельные компоненты.
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
}
Вопросы на собесе (27)
constructor (4)
- Как рекомендуется объявлять переменные в конструкторе data-класса?
Использовать
val
для неизменяемых полей (код более безопасный и предсказуемый).
- Можно ли описать data-класс с пустым конструктором, но с полями внутри класса?
Нет нельзя.
- Можно ли создавать вторичные конструкторы в data class?
Да, но они должны вызывать первичный конструктор, чтобы корректно инициализировать все свойства класса.
- Как будут вычесляться методы если указать вторичный конструктор?
Если в data class указать вторичный конструктор, то методы equals, hashCode, toString, и copy будут по-прежнему вычисляться на основе свойств, объявленных в главном конструкторе, даже если вы добавите дополнительные конструкторы
- Как рекомендуется объявлять переменные в конструкторе data-класса?
Methods (7)
- Перечисли методы data-класса?
equals()
hashCode()
toString()
сopy()
componentN()
- Kакие методы переопределены в data class?
equals()
hashCode()
toString()
- На основе чего вычисляются методы в data class?
На основе полей в первичном конструкторе.
- Как работает метод copy?
Позволяет создавать новый экземпляр объекта с измененными значениями выбранных свойств. Это сохраняет неизменяемость исходного объекта и позволяет легко создавать модифицированные копии.
- Что произойдет если вызвать метод copy без аргументов?
Будет создан новый объект, идентичный исходному, с копированием всех значений свойств. То есть, будет скопирован объект с теми же параметрами, что и у оригинала.
- Какой будет результат если сравнить через === data-класс и его копию созданную через copy() без аргументов?
Результат будет false, так как это два разных объекта в памяти.
- Как работает метод componentN?
Методы
componentN
автоматически генерируются дляdata class
и возвращают свойства объекта по порядку. Это позволяет удобно извлекать значения, например, при деструктивном присваивании.
- Перечисли методы data-класса?
Другие (16)
- Что такое data class в Kotlin?
Класс для хранения данных и автоматической генерации методов. Они упрощают работу с неизменяемыми объектами и обеспечивают удобный способ управления состоянием.
- Какие ограничения есть у data class?
• Минимум 1 параметр в первичном конструкторе
val
илиvar
.• Не может быть
abstract
open
sealed
inner
.
- Как data-класс вычисляет хэшкод?
На основе всех полей, объявленных в первичном конструкторе класса. Используется метод
Objects.hash()
из Java.
- Что сделать чтобы поле не участвовало в вычислении хэшкода в data-классе?
• Перенести поле из первичного конструктора в тело
data
-класса.• Переопределить и переписать метод
hashCode()
.
- Можно ли наследоваться от data class? (расширить его)
Нет.
- Почему в Kotlin запретили наследоваться от data-класса?
В Kotlin запретили наследование от
data
-классов, чтобы сохранить целостность и корректность автоматически сгенерированных методов, таких какequals
,hashCode
,toString
иcopy
. Наследование могло бы привести к нарушению этих свойств, так как дочерний класс мог бы изменять поведение или данные, что привело бы к некорректным результатам в этих методах.
- Как будут использоваться поля при наследовании data class от другого класса?
Поля с одинаковыми именами должны быть переопределены в
data class
с помощьюoverride
и бытьopen
в базовом классе.
- Есть ли в Kotlin средства чтобы не приходилось вручную переопределять equals и hashCode для классов которые мы создаем?
Да, data-классы.
- В чем может быть опасность объявления лямбды в первичном конструкторе data-класса?
Если в
data
-классе лямбда указана в конструкторе, то два экземпляра, даже с одинаковыми параметрами, могут вернутьfalse
при сравнении, так как лямбды не равны друг другу по значению. Каждый экземпляр лямбды является уникальным, поэтомуequals
вернётfalse
, даже если они функционально идентичны.
- Как хранить лямбды в data-классе, чтобы объекты корректно сравнивались?
Хранить их вне конструктора, в теле класса. Это исключит их из
equals
иhashCode
, сохраняя корректное сравнение объектов.
- Сколько объектов будет в set и какие именно?
data class Dog( val breed: String = "shepherd" ) { var name = "" } val set = hashSetOf( Dog().apply { name = "Joe" }, Dog("sharik"), Dog().apply { name = "Henry" } ) println(set)
В
Set
будет 2 объекта:[Dog(breed=shepherd), Dog(breed=sharik)]
.Dog(breed = “shepherd”).name = “Joe”
.
Dog(breed = “sharik”).name = “”
.
- Каким будет результат сравнения двух объектов?
data class Person( val name: String ) { var age: Int = 0 } val person1 = Person("John") val person2 = Person("John") person1.age = 10 person2.age = 20 person1 == person2 ???
Результат будет true. Метод
equals
автоматически сгенерирован так, что он сравнивает только параметры конструктора (в данном случае толькоname
). Полеage
не участвует в сравнении, так как оно не является частью первичного конструктора.
- Что напечатает println?
data class A( var field: String = "" ) fun func(a: A) { a.field = "d" } val a = A() a.field = "c" func(a) print(a.field)
d
- Какой из указанных модификаторов нельзя использовать с 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()
- Что могут делать data классы из нижеперечисленного? (Может быть несколько вариантов ответов)
• Наследоваться от других дата классов.
• Наследоваться от других классов.
• Имплементировать интерфейсы.
• Не могут все вышеперечисленное.
- Что такое data class в Kotlin?