Классы данных
Не является необычным создание классов, основное назначение которых — хранение данных. В таких классах часто механически выводимая стандартная функциональность и некоторые вспомогательные функции часто выводимы из данных. В 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и возвращают совместимые типы, соответствующие функции генерируются для класса данных и переопределяют функции супертипа. Если функции супертипа не могут быть переопределены из-за несовместимых сигнатур или из-за того, что они являются финальными, то генерируется ошибка.Предоставление явных реализаций для функций
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