Spec-Zone.ru › Kotlin 1.4

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

Мы часто создаём классы, основное назначение которых — хранение данных. В таком классе стандартные функции и утилиты часто могут быть автоматически выведены из данных. В Kotlin это называется классом данных и отмечается как data.

data class User(val name: String, val age: Int)

Компилятор автоматически выводит следующие члены из всех свойств, объявленных в первичном конструкторе:

  • equals()/hashCode() пару;
  • toString() вида "User(name=John, age=42)";
  • componentN() функции, соответствующие свойствам в порядке их объявления;
  • copy() функцию (см. ниже).

Для обеспечения согласованности и осмысленного поведения генерируемого кода, классы данных должны удовлетворять следующим требованиям:

  • Первичный конструктор должен иметь по крайней мере один параметр;
  • Все параметры первичного конструктора должны быть помечены как val или var;
  • Классы данных не могут быть абстрактными, открытыми, запечатанными или вложенными;
  • (до версии 1.1) Классы данных могут реализовывать только интерфейсы.

Кроме того, генерация членов следует этим правилам относительно наследования членов:

  • Если есть явные реализации equals(), hashCode() или toString() в теле класса данных или final реализации в суперклассе, то эти функции не генерируются, и используются существующие реализации;
  • Если у супертипа есть componentN() функции, которые являются open и возвращают совместимые типы, соответствующие функции генерируются для класса данных и переопределяют функции супертипа. Если функции супертипа не могут быть переопределены из-за несовместимых сигнатур или являются final, выводится ошибка;
  • Наследование класса данных от типа, у которого уже есть функция copy(...) с соответствующей сигнатурой, устарело в Kotlin 1.2 и запрещено в Kotlin 1.3.
  • Явные реализации функций componentN() и copy() запрещены.

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

В 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(). Хотя у двух объектов 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–2020 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/reference/data-classes.html

Spec-Zone.ru

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