Spec-Zone.ru › Kotlin 1.9

Классы данных

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

Классы данных могут расширять другие классы (см. Закрытые классы для примеров).

В JVM, если сгенерированный класс должен иметь конструктор без параметров, необходимо указать значения по умолчанию для свойств (см. Конструкторы).

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(). Свойство age не может быть использовано внутри реализаций toString(), equals(), hashCode(), и copy(), потому что оно объявлено внутри тела класса. Если два объекта Person имеют разный возраст, но одинаковый name, они считаются равными. Это потому, что функция equals() может проверять только равенство свойства name. Например:

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

    println("person1 == person2: ${person1 == person2}")
    // person1 == person2: true
  
    println("person1 with age ${person1.age}: ${person1}")
    // person1 with age 10: Person(name=John)
  
    println("person2 with age ${person2.age}: ${person2}")
    // person2 with age 20: Person(name=John)
//sampleEnd
}

Копирование

Используйте функцию 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. Однако в большинстве случаев использование именованных классов данных — лучший выбор, так как это делает код более читабельным, предоставляя осмысленные имена для свойств.

Последнее изменение: 25 июля 2023 г.
Расширения Закрытые классы и интерфейсы

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API