Классы данных
Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 32 из 57.
Класс данных — это класс, основная задача которого заключается в хранении данных. Модификатор data заставляет компилятор сгенерировать toString(), equals(), hashCode(), copy() и componentN() на основе свойств первичного конструктора:
data class Point(val x: Int, val y: Int)Внутри main:
val a = Point(1, 2)
val b = Point(1, 2)
println(a)
println(a == b)
println(setOf(a, b).size)Вывод:
Point(x=1, y=2)
true
1Без data println показывает имя класса и хеш-код, например Point@1b6d3586, а два объекта с одинаковыми значениями не равны. copy() создаёт новый объект с изменёнными некоторыми свойствами и оставляет исходный без изменений, поэтому класс данных со свойствами val работает как неизменяемое значение:
data class User(val name: String, val email: String, val admin: Boolean = false)Внутри main:
val ada = User("Ada", "ada@example.com")
val boss = ada.copy(admin = true)
println(ada)
println(boss)
println(ada == boss)Вывод:
User(name=Ada, email=ada@example.com, admin=false)
User(name=Ada, email=ada@example.com, admin=true)
falseДеструктурирующие объявления распаковывают объект в переменные: val (x, y) = point вызывают сгенерированные component1() и component2() в порядке конструктора. Это также работает в циклах for и параметрах лямбда-выражений, а _ пропускает свойство:
data class Score(val player: String, val points: Int, val level: Int)Внутри main:
val scores = listOf(Score("ada", 120, 3), Score("bo", 95, 2))
for ((player, points) in scores) println("$player: $points")
val (_, bestPoints, bestLevel) = scores.maxBy { it.points }
println("best: $bestPoints at level $bestLevel")Вывод:
ada: 120
bo: 95
best: 120 at level 3Участвуют только свойства первичного конструктора: свойство, объявленное в теле класса, не включается в toString, equals, hashCode и copy. Класс данных должен иметь как минимум один параметр конструктора, и каждый параметр должен быть val или var:
data class Reading(val sensor: String, val value: Int) {
var note = ""
}Внутри main:
val r1 = Reading("t1", 20)
val r2 = Reading("t1", 20)
r1.note = "checked"
println(r1)
println(r1 == r2)Вывод:
Reading(sensor=t1, value=20)
trueЗадание
ЛегкоСделайте Book классом данных, чтобы он выводился и сравнивался по значению. Затем реализуйте три функции: parse(line) преобразует Dune;Herbert;1965 в Book, newEdition(book, year) возвращает копию с новым годом и добавленным к названию (new edition), а describe(book) возвращает Dune by Herbert, 1965 с использованием деструктурирующего объявления.
Предоставленный код разбирает каждую входную строку, выводит каждую книгу, количество дубликатов, новое издание первой книги (год 2024) и описание каждой уникальной книги.
Ваш код должен находиться в Book.kt и BookTools.kt. В Main.kt содержится предоставленный код ввода/вывода, и его нельзя изменять.
Попробуйте сами
fun main() {
// Предоставленный код ввода/вывода: оставьте его как есть
val input = generateSequence(::readLine).toList()
val books = input.map { parse(it) }
for (b in books) println(b)
println("duplicates: ${books.size - books.distinct().size}")
println(newEdition(books[0], 2024))
for (b in books.distinct()) println(describe(b))
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПервичные конструкторыБлоки init и валидацияВторичные конструкторыПовторение — читательский билет4Наследование
Открытые классы и подклассыПереопределение членовsuper и конструкторыАбстрактные классыПовторение — каталог сотрудников7Специальные классы
Классы данныхКлассы перечисленийЗапечатанные иерархииequals, hashCode, toStringПовторение — трекер заказов10Паттерны проектирования. Часть 2
Делегирование с помощью byПаттерн декораторПаттерн строительПаттерн состояние2Свойства и инкапсуляция
Пользовательские аксессорыМодификаторы видимостиПриватные сеттерыlazy и lateinitПовторение — банковский счёт5Интерфейсы
Объявление интерфейсовМетоды по умолчаниюМножественные интерфейсыИнтерфейсы как типыПовторение — способы оплаты8Обобщения
Обобщённые функцииОбобщённые классыОграничения типовВариативность с in и outПовторение — очередь с приоритетом11Проект: Управление библиотекой
Книги и читателиВыдача книг3Объекты и компаньоны
Объявления объектовОбъекты-компаньоныКонстанты с constОбъектные выраженияПовторение — билетная касса6Полиморфизм
Динамическая диспетчеризацияПроверка типов и умные приведения типовwhen с типамиФункции-расширенияПовторение — смотритель зоопарка9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Песочница Kotlin