Menu
Coddy logo textTech

データクラス

CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 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のようなハッシュコードを表示し、同じ値を持つ2つのオブジェクトは等しくありません。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から除外されます。データクラスには少なくとも1つのコンストラクターパラメーターが必要で、すべてのパラメーターは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
challenge icon

チャレンジ

簡単

Bookをデータクラスにして、値によって出力および比較が行われるようにします。次に、3つの関数を完成させます。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))
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Kotlinプレイグラウンド