Spec-Zone.ru › Kotlin 2

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

Классы данных в 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
}

В примере ниже по умолчанию в реализациях toString(), equals(), hashCode() и copy() используется только свойство name, а функция-компонент всего одна — component1(). Свойство age объявлено в теле класса и не учитывается. Поэтому два объекта Person с одинаковым значением name, но разными значениями age считаются равными, поскольку equals() учитывает только свойства первичного конструктора:

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)

Функция copy() создаёт поверхностную копию экземпляра. Иными словами, она не копирует компоненты рекурсивно. В результате ссылки на другие объекты остаются общими.

Например, если свойство содержит изменяемый список, изменения, внесённые через «исходное» значение, также видны через копию, а изменения, внесённые через копию, видны в исходном объекте:

data class Employee(val name: String, val roles: MutableList<String>)

fun main() {
    val original = Employee("Jamie", mutableListOf("developer"))
    val duplicate = original.copy()

    duplicate.roles.add("team lead")

    println(original) 
    // Employee(name=Jamie, roles=[developer, team lead])
    println(duplicate) 
    // Employee(name=Jamie, roles=[developer, team lead])
}

Как видно, изменение свойства duplicate.roles также меняет свойство original.roles, поскольку оба свойства содержат ссылку на один и тот же список.

Классы данных и объявления деструктуризации

Функции-компоненты, генерируемые для классов данных, позволяют использовать их в объявлениях деструктуризации:

val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") 
// Jane, 35 years of age

Стандартные классы данных

Стандартная библиотека предоставляет классы Pair и Triple. Однако в большинстве случаев лучше использовать именованные классы данных: благодаря осмысленным названиям свойств код становится понятнее.

14 марта 2026 г.
КлассыРасширения

© 2010–2026 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