Menu
Coddy logo textTech

Klasy danych

Część sekcji Programowanie obiektowe ścieżki Kotlin w Coddy. Lekcja 32 z 57.

Klasa danych to klasa, której głównym zadaniem jest przechowywanie danych. Modyfikator data sprawia, że kompilator generuje metody toString(), equals(), hashCode(), copy() i componentN() na podstawie właściwości konstruktora podstawowego:

data class Point(val x: Int, val y: Int)

Wewnątrz main:

val a = Point(1, 2)
val b = Point(1, 2)
println(a)
println(a == b)
println(setOf(a, b).size)

Wynik:

Point(x=1, y=2)
true
1

Bez data println wyświetla nazwę klasy i kod hash, taki jak Point@1b6d3586, a dwa obiekty o tych samych wartościach nie są sobie równe. copy() tworzy nowy obiekt ze zmienionymi niektórymi właściwościami i pozostawia oryginał bez zmian, więc klasa danych z właściwościami val działa jak niezmienna wartość:

data class User(val name: String, val email: String, val admin: Boolean = false)

Wewnątrz main:

val ada = User("Ada", "ada@example.com")
val boss = ada.copy(admin = true)
println(ada)
println(boss)
println(ada == boss)

Wynik:

User(name=Ada, email=ada@example.com, admin=false)
User(name=Ada, email=ada@example.com, admin=true)
false

Deklaracje destrukturyzujące rozpakowują obiekt do zmiennych: val (x, y) = point wywołuje wygenerowane component1() i component2() w kolejności konstruktora. Działa to również w pętlach for i parametrach lambdy, a _ pomija właściwość:

data class Score(val player: String, val points: Int, val level: Int)

Wewnątrz 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")

Wynik:

ada: 120
bo: 95
best: 120 at level 3

Uwzględniane są tylko właściwości z konstruktora głównego: właściwość zadeklarowana w treści klasy jest pomijana w toString, equals, hashCode i copy. Klasa danych musi mieć co najmniej jeden parametr konstruktora, a każdy parametr musi być typu val lub var:

data class Reading(val sensor: String, val value: Int) {
    var note = ""
}

Wewnątrz main:

val r1 = Reading("t1", 20)
val r2 = Reading("t1", 20)
r1.note = "checked"
println(r1)
println(r1 == r2)

Wynik:

Reading(sensor=t1, value=20)
true
challenge icon

Wyzwanie

Łatwy

Zrób z Book klasę danych, aby była drukowana i porównywana według wartości. Następnie uzupełnij trzy funkcje: parse(line) zamienia Dune;Herbert;1965 w obiekt Book, newEdition(book, year) zwraca kopię z nowym rokiem i dodanym do tytułu tekstem (new edition), a describe(book) zwraca Dune by Herbert, 1965 z użyciem deklaracji destrukturyzującej.

Dostarczony kod parsuje każdy wiersz wejściowy, drukuje każdą książkę, liczbę duplikatów, nowe wydanie pierwszej książki (rok 2024) oraz opis każdej unikalnej książki.

Umieść swój kod w plikach Book.kt i BookTools.kt. Plik Main.kt zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

fun main() {
    // Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
    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))
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Edytor online Kotlin