Классы данных
Несложно создавать классы, основное назначение которых — хранение данных. В таких классах часто стандартные функции и вспомогательные функции можно автоматически вывести из данных. В Kotlin такие классы называются классами данных и помечаются как data.
data class User(val name: String, val age: Int)
Компилятор автоматически выводит следующие члены из всех свойств, объявленных в первичном конструкторе:
equals()/hashCode()паруtoString()вида"User(name=John, age=42)"componentN()функции, соответствующие свойствам в порядке их объявления.copy()функцию (см. ниже).
Для обеспечения согласованности и осмысленного поведения сгенерированного кода, классы данных должны соответствовать следующим требованиям:
Первичный конструктор должен иметь хотя бы один параметр.
Все параметры первичного конструктора должны быть помечены как
valилиvar.Классы данных не могут быть абстрактными, открытыми, закрытыми или вложенными.
Кроме того, генерация членов класса данных следует этим правилам по отношению к наследованию членов:
Если в теле класса данных есть явные реализации
equals(),hashCode(), илиtoString(), или реализацииfinalв родительском классе, то эти функции не генерируются, и используются существующие реализации.Если супертип имеет
componentN()функции, которыеopenи возвращают совместимые типы, соответствующие функции генерируются для класса данных и переопределяют функции супертипа. Если функции супертипа не могут быть переопределены из-за несовместимых сигнатур или из-за того, что они являются final, сообщается об ошибке.Явные реализации функций
componentN()иcopy()недопустимы.
Классы данных могут расширять другие классы (см. Закрытые классы для примеров).
data class User(val name: String = "", val age: Int = 0)
Свойства, объявленные в теле класса
Компилятор использует только свойства, определенные внутри первичного конструктора, для автоматически сгенерированных функций. Чтобы исключить свойство из сгенерированных реализаций, объявите его в теле класса:
data class Person(val name: String) {
var age: Int = 0
}
Только свойство name будет использоваться внутри реализаций toString(), equals(), hashCode(), и copy(), и будет только одна функция компонента component1(). Хотя у двух объектов Person могут быть разные возраста, они будут считаться равными.
data class Person(val name: String) {
var age: Int = 0
}
fun main() {
//sampleStart
val person1 = Person("John")
val person2 = Person("John")
person1.age = 10
person2.age = 20
//sampleEnd
println("person1 == person2: ${person1 == person2}")
println("person1 with age ${person1.age}: ${person1}")
println("person2 with age ${person2.age}: ${person2}")
}
Копирование
Используйте функцию copy() для копирования объекта, позволяя изменять некоторые его свойства, оставляя остальные неизменными. Реализация этой функции для класса User выше будет следующей:
fun copy(name: String = this.name, age: Int = this.age) = User(name, age)
Затем вы можете написать следующее:
val jack = User(name = "Jack", age = 1) val olderJack = jack.copy(age = 2)
Классы данных и деструктурирующие объявления
Функции компонентов, сгенерированные для классов данных, позволяют использовать их в деструктурирующих объявлениях:
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"
Стандартные классы данных
Стандартная библиотека предоставляет классы Pair и Triple. Однако в большинстве случаев именованные классы данных являются лучшим выбором, так как они делают код более читаемым, предоставляя осмысленные имена для свойств.
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/data-classes.html