Классы данных
Не является необычным создавать классы, основное назначение которых — хранение данных. В таких классах стандартные функциональные возможности и вспомогательные функции часто могут быть получены автоматически из данных. В Kotlin они называются классами данных и помечаются следующим образом data:
data class User(val name: String, val age: Int)
Компилятор автоматически вычисляет следующие члены по всем свойствам, объявленным в первичном конструкторе:
equals()/hashCode()паруtoString()вида"User(name=John, age=42)"componentN()функции, соответствующие свойствам в порядке их объявления.copy()функцию (см. ниже).
Для обеспечения согласованности и осмысленного поведения сгенерированного кода классы данных должны удовлетворять следующим требованиям:
Первичный конструктор должен иметь по крайней мере один параметр.
Все параметры первичного конструктора должны быть помечены как
valилиvar.Классы данных не могут быть абстрактными, открытыми, запечатанными или внутренними.
Кроме того, генерация членов класса данных подчиняется следующим правилам в отношении наследования членов:
Если в теле класса данных или в реализации
finalсуперкласса существуют явные реализацииequals(),hashCode(), илиtoString(), то эти функции не генерируются, и используются существующие реализации.Если супертип имеет
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–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/data-classes.html