Прямые ссылки на публичные уроки для быстрого старта и стабильной индексации lesson-страниц.
Классические классы используются для организации кода и реализации ООП-подходов. Создатели Kotlin добавили специальный тип классов для хранения данных — Data классы. Строго говоря, это обычные классы с дополнительными встроенными возможностями.
Data классы автоматически предоставляют следующие методы:
equals() — сравнение двух объектов по значениям полей;hashCode() — уникальный целочисленный код объекта;toString() — строковое представление объекта с именами и значениями полей;copy() — копирование объекта с возможностью изменить отдельные поля.При попытке распечатать объект обычного класса в консоль получим нечитаемую строку вида additional.Word@452b3a41 — это стандартное строковое представление объекта.
class Word( val text: String, val translate: String, ) fun main(){ val word = Word("Red", "Красный") println(word) }
Вызов println(word.toString()) даёт тот же результат, так как println() использует toString() под капотом.
Вариант 1. Переопределить toString() вручную в теле класса:
class Word( val text: String, val translate: String, ) { override fun toString(): String { return "Word(text='$text', translate='$translate')" } }
Вариант 2. Добавить ключевое слово data — тело класса не нужно, результат идентичен:
fun main(){ val word = Word("Red", "Красный") println(word) } data class Word( val text: String, val translate: String, )
При необходимости toString() можно переопределить и в Data классе.
equals() аналогичен оператору ==. При сравнении объектов обычного класса сравниваются ссылки на объекты в памяти, а не значения полей — оба результата будут false. Data класс сравнивает именно значения:
fun main(){ val word1 = Word("Red", "Красный") val word2 = Word("Red", "Красный") val word3 = Word("White", "Белый") println(word1 == word2) // true println(word2 == word3) // false }
Оператор ссылочного сравнения === не связан с equals() и ведёт себя одинаково для обоих типов классов.
Функция copy() умеет копировать объект целиком:
fun main(){ val word1 = Word("Red", "Красный") val word2 = Word("Red", "Красный") val word3 = Word("White", "Белый") val word4 = word3.copy() println(word4) }
А также копировать объект с выборочным изменением полей:
fun main(){ val word1 = Word("Red", "Красный") val word2 = Word("Red", "Красный") val word3 = Word("White", "Белый") val word4 = word3.copy(translate = "Правильный перевод: Белый") println(word3) println(word4) }
Это часто применяется в мобильной разработке: когда в состоянии экрана меняется только одно поле, copy() позволяет создать новый объект с изменённым значением, сохранив остальные. Метод copy() доступен только для Data классов.
Метод присутствует в обоих типах классов, но в Data классе он переопределён. Метод возвращает уникальный целочисленный код объекта и может использоваться для сравнения — быстрее, чем equals(), так как сравнивать два числа эффективнее, чем все свойства объекта. Два Data-объекта с одинаковыми полями имеют одинаковый хэш-код:
println(word1.hashCode()) println(word2.hashCode())
В Data классе hashCode() вычисляется на основе полей:
public int hashCode() { String var10000 = this.original; int var1 = (var10000 != null ? var10000.hashCode() : 0) * 31; String var10001 = this.translate; return var1 + (var10001 != null ? var10001.hashCode() : 0); }
Обычные классы используют hashCode() базового класса Object, который не учитывает поля и возвращает разные значения для каждого объекта:
public class Object { //... @IntrinsicCandidate public native int hashCode(); //... }