【Kotlin】レッスン5-12:データクラスを理解しよう|equalsやcopyの仕組みも解説

一つ前のページではインターフェースについて学習しました。
今回は データクラス について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:コレクション編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:プライマリコンストラクタを理解しよう
・Lesson5-3:セカンダリコンストラクタを理解しよう
・Lesson5-4:ふたつのコンストラクタを使いこなそう
・Lesson5-5:アクセス修飾子とカプセル化を理解しよう
・Lesson5-6:静的メンバとインスタンスメンバを理解しよう
・Lesson5-7:クラスの継承を理解しよう
・Lesson5-8:メソッドのオーバーライドを理解しよう
・Lesson5-9:クラスを拡張しよう
・Lesson5-10:抽象クラスを理解しよう
・Lesson5-11:インターフェースを理解しよう
・Lesson5-12:データクラスを理解しよう ◁今回はココ
・確認問題5-☆1:モンスター捕獲ゲームを作ろう
・確認問題5-☆2:マルバツゲームを作ろう
・確認問題5-☆3:石取りゲームを作ろう
データクラス入門|自動生成メソッドと定義方法を解説

プログラミングでは、データを管理するためにクラスを使用することがよくあります。
Kotlinには「データクラス」という特別なクラスがあり、簡単かつ効率的にデータを管理する機能を提供します。
この章ではデータクラスの特性と使い方を詳しく解説します。

データクラスの概要と基本構文
データクラスはKotlinが提供する特別なクラスで、主にデータを格納する目的で設計されています。
以下のような特徴があります。
- データを保持することを目的とする:ユーザーや設定情報などを表現するのに最適。
- 便利なメソッドを自動生成:
equals(),hashCode(),toString(),copy()などが自動生成される。 - データ構造のシンプル化:コードの記述量を大幅に削減
データクラスを定義するには dataキーワード を使用します。
基本構文は以下の通りです。
data class データクラス名(val プロパティ名: 型, val プロパティ名: 型, ...)
データクラスを定義すると、そのクラス内には以下のようなインスタンスメソッドが自動的に生成します。
equals():オブジェクトの内容を比較。hashCode():オブジェクトのハッシュ値を計算。toString():クラスの内容を文字列として表現。copy():オブジェクトの複製を作成。
データクラスの使い方|各インスタンスメソッドの使用コード例
実際にデータクラスを使った例を見てみましょう。
equals()メソッドの意味と使用コード例
equals()メソッド はオブジェクトの内容が等しいかどうかを比較する際に使用されます。
通常のクラスではequals()メソッドを手動でオーバーライドしない限り、参照アドレスが比較されます。
しかしデータクラスではこのメソッドが自動生成され、プロパティの値を基準に比較します。
data class User(val id: Int, val name: String) // 2つのプロパティを持つデータクラスの定義
fun main() {
val user1 = User(1, "Alice") // インスタンス生成
val user2 = User(1, "Alice") // インスタンス生成
val user3 = User(2, "Bob") // インスタンス生成
println(user1 == user2) // true(idとnameが同じ)
println(user1 == user3) // false(idやnameが異なる)
}通常のクラスでは==は参照の比較を行いますが、データクラスでは内容が同じならtrueを返すように自動的に変更されています。
hashCode()メソッドの意味と使用コード例
hashCode()メソッドはオブジェクトのハッシュ値を計算します。
この値は主にハッシュベースのコレクション(例: HashMap, HashSet)で使用されます。
data class User(val id: Int, val name: String) // データクラスの定義
fun main() {
val user1 = User(1, "Alice") // インスタンス生成
val user2 = User(1, "Alice") // インスタンス生成
val userSet = hashSetOf(user1)
println(userSet.contains(user2)) // true(内容が同じオブジェクトを認識)
}通常のクラスではhashCode()をオーバーライドしないと意味のある値を返しませんが、データクラスは内容に基づいたハッシュ値を生成します。
toString()メソッドの意味と使用コード例
toString()メソッドはオブジェクトの内容を文字列として簡単に確認できるようにします。
特にデバッグ時やログ出力時に便利です。
data class User(val id: Int, val name: String) // データクラスの定義
fun main() {
val user1 = User(1, "Alice") // インスタンス生成
println(user1) // User(id=1, name=Alice)
}通常のクラスではtoString()をオーバーライドしないと意味のない情報(参照アドレス)が表示されますが、データクラスではプロパティとその値をわかりやすく文字列化します。
copy()メソッドの意味と使用コード例
copy()メソッドはオブジェクトを複製し、一部のプロパティを変更した新しいオブジェクトを作成できます。
data class User(val id: Int, val name: String) // データクラスの定義
fun main() {
val user1 = User(1, "Alice") // インスタンス生成
val user2 = user1.copy(name = "Bob") // nameだけ変更
println(user1) // User(id=1, name=Alice)
println(user2) // User(id=1, name=Bob)
}元のオブジェクトはそのまま保持されるため、不変性を保ちながらデータを変更する場面で役立ちます。
データクラスの利点と使いどころを押さえよう
データクラスは以下のようなシナリオで特に役立ちます。
- データの管理が主な目的の場合: 例えばデータベースのエントリやAPIレスポンスを扱う際に便利。
- データの比較や複製が必要な場合: 自動生成される
equals()やcopy()が役立ちます。 - シンプルなデータモデル: 設計を簡略化し、読みやすいコードを作成できます。
まとめ|データクラスを使いこなそう
データクラスはKotlinが提供する非常に便利なクラス構造で、データを扱う場面でコードを簡潔かつ効率的に記述するための強力なツールです。
特に以下の点が重要です。
dataキーワードを使用して簡単に定義。- 自動生成される主要なメソッドで作業を効率化。
- データ保持に特化したシンプルな設計。
データクラスを活用することで、コードの可読性と生産性を向上させることができます。
練習問題|Kotlinのデータクラスで顧客情報を管理するプログラムを作ろう

顧客情報を管理するシステムを作成しましょう。
このシステムでは顧客の名前と年齢を管理し、顧客リストを表示する機能を持ちます。また特定の年齢以上の顧客を検索する機能も実装します。
この問題の要件
以下の要件に従ってコードを完成させてください。
- 顧客情報を表すデータクラス
Customerを作成し、name(名前)とage(年齢)プロパティを持つこと。 - 顧客情報を管理する
CustomerManagerクラスを作成し、顧客を追加するメソッド、すべての顧客情報を表示するメソッド、指定された年齢以上の顧客情報を表示するメソッドを実装すること。 - メイン関数で
CustomerManagerクラスのインスタンスを作成し、複数のCustomerインスタンスを追加して、全顧客情報と指定された年齢以上の顧客情報を表示すること。
ただし、以下のような実行結果となること。
顧客「山田太郎」が追加されました。 顧客「佐藤花子」が追加されました。 顧客「田中一郎」が追加されました。 すべての顧客情報: 名前: 山田太郎, 年齢: 28 名前: 佐藤花子, 年齢: 22 名前: 田中一郎, 年齢: 35 年齢 25 以上の顧客情報: 名前: 山田太郎, 年齢: 28 名前: 田中一郎, 年齢: 35
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:データクラスCustomerの定義
□ プライマリコンストラクタとして、nameとageのプロパティを持つ
2:クラスCustomerManagerの定義
□ privateなMutableListとしてcustomersプロパティを宣言
□ addCustomerメソッドの定義
□ □ customersリストに引数customerを追加
□ □ printlnを用いて顧客の追加メッセージを出力
□ displayAllCustomersメソッドの定義
□ □ printlnを用いて「すべての顧客情報:」を出力
□ □ for文を用いてcustomersリスト内の各顧客を繰り返し処理
□ □ □ 各顧客の名前と年齢を埋め込み文字列で出力
□ displayCustomersAboveAgeメソッドの定義
□ □ printlnを用いて「指定された年齢以上の顧客情報:」を出力
□ □ for文を用いてcustomersリスト内の各顧客を繰り返し処理
□ □ □ if文を用いて顧客の年齢が指定された値以上か判定
□ □ □ □ 条件を満たす場合、顧客の名前と年齢を埋め込み文字列で出力
3:main関数の定義
□ CustomerManagerクラスのインスタンスを作成し、managerに代入
□ Customerクラスのインスタンスを作成し、customer1, customer2, customer3に代入
□ addCustomerメソッドを用いて各顧客をmanagerに追加
□ displayAllCustomersメソッドを用いてすべての顧客情報を表示
□ displayCustomersAboveAgeメソッドを用いて指定された年齢以上の顧客情報を表示
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
// 顧客情報を表すデータクラス Customer を定義 data class Customer(val name: String, val age: Int) // 顧客情報を管理するクラス CustomerManager を定義 class CustomerManager { // 顧客リストを保持するプロパティ private val customers: MutableList<Customer> = mutableListOf() // 顧客を追加するメソッド fun addCustomer(customer: Customer) { customers.add(customer) println("顧客「${customer.name}」が追加されました。") } // すべての顧客情報を表示するメソッド fun displayAllCustomers() { println("すべての顧客情報:") /*【穴埋め問題1】 ここに for 文を使って、すべての顧客情報を表示するコードを書いてください。Customer クラスの name と age を出力します。 */ } // 指定された年齢以上の顧客情報を表示するメソッド fun displayCustomersAboveAge(age: Int) { println("年齢 $age 以上の顧客情報:") /*【穴埋め問題2】 ここに for 文と if 文を使って、指定された年齢以上の顧客情報を表示するコードを書いてください。Customer クラスの name と age を出力します。 */ } } // メイン関数 fun main() { // CustomerManager のインスタンスを作成 val manager = CustomerManager() // Customer のインスタンスを作成 /*【穴埋め問題3】 ここに Customer クラスのインスタンスを作成するコードを書いてください。顧客の名前と年齢を指定します。 */ // 顧客を追加 /*【穴埋め問題4】 ここに作成した顧客を CustomerManager に追加するコードを書いてください。 */ // すべての顧客情報を表示 manager.displayAllCustomers() // 指定された年齢以上の顧客情報を表示 manager.displayCustomersAboveAge(25) }
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
// 顧客情報を表すデータクラス Customer を定義 data class Customer(val name: String, val age: Int) // 顧客情報を管理するクラス CustomerManager を定義 class CustomerManager { // 顧客リストを保持するプロパティ private val customers: MutableList<Customer> = mutableListOf() // 顧客を追加するメソッド fun addCustomer(customer: Customer) { customers.add(customer) println("顧客「${customer.name}」が追加されました。") } // すべての顧客情報を表示するメソッド fun displayAllCustomers() { println("すべての顧客情報:") for (customer in customers) { // 繰り返し処理 println("名前: ${customer.name}, 年齢: ${customer.age}") } } // 指定された年齢以上の顧客情報を表示するメソッド fun displayCustomersAboveAge(age: Int) { println("年齢 $age 以上の顧客情報:") for (customer in customers) { // 繰り返し処理 if (customer.age >= age) { // 分岐処理 println("名前: ${customer.name}, 年齢: ${customer.age}") } } } } // メイン関数 fun main() { // CustomerManager のインスタンスを作成 val manager = CustomerManager() // Customer のインスタンスを作成 val customer1 = Customer("山田太郎", 28) val customer2 = Customer("佐藤花子", 22) val customer3 = Customer("田中一郎", 35) // 顧客を追加 manager.addCustomer(customer1) manager.addCustomer(customer2) manager.addCustomer(customer3) // すべての顧客情報を表示 manager.displayAllCustomers() // 指定された年齢以上の顧客情報を表示 manager.displayCustomersAboveAge(25) }
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
データクラス
Customerの定義data class Customer(val name: String, val age: Int)
data class: データを表現するためのKotlin独自のクラス。以下の機能が自動生成されます:toStringメソッド: クラスのインスタンスを文字列で表現。equalsメソッド: インスタンスの比較。copyメソッド: 新しいオブジェクトのコピーを簡単に作成。hashCodeメソッド: オブジェクトの一意性を担保。
このクラスでは顧客の名前(
name)と年齢(age)を保持するプロパティを定義しています。顧客管理クラス
CustomerManagerの定義class CustomerManager { private val customers: MutableList<Customer> = mutableListOf() }class: クラスの定義キーワード。オブジェクト指向プログラミングの基本概念。MutableList: 要素の追加や削除が可能なリスト。private修飾子: 外部から直接アクセスできないように制限。
このプロパティは顧客情報を保持するために使用されます。
顧客を追加するメソッド
fun addCustomer(customer: Customer) { customers.add(customer) println("顧客「${customer.name}」が追加されました。") }fun: 関数を定義するキーワード。- 文字列補間(
${}): 文字列内で変数や式を直接使用する構文。
このメソッドは顧客リストに新しい顧客を追加し、追加された旨を表示します。
すべての顧客情報を表示するメソッド
fun displayAllCustomers() { println("すべての顧客情報:") for (customer in customers) { println("名前: ${customer.name}, 年齢: ${customer.age}") } }forループ: コレクション内の要素を1つずつ処理。println: 標準出力に文字列を表示。
このメソッドは登録された全顧客の情報を表示します。
指定された年齢以上の顧客を表示するメソッド
fun displayCustomersAboveAge(age: Int) { println("年齢 $age 以上の顧客情報:") for (customer in customers) { if (customer.age >= age) { println("名前: ${customer.name}, 年齢: ${customer.age}") } } }- 条件分岐(
if文): 条件を満たす場合にのみ処理を実行。 - 比較演算子(
>=): 2つの値を比較して真偽を返します。
指定された年齢以上の顧客をリストアップします。
メイン関数と実行例
fun main() { val manager = CustomerManager() val customer1 = Customer("山田太郎", 28) val customer2 = Customer("佐藤花子", 22) val customer3 = Customer("田中一郎", 35) manager.addCustomer(customer1) manager.addCustomer(customer2) manager.addCustomer(customer3) manager.displayAllCustomers() manager.displayCustomersAboveAge(25) }main関数: Kotlinプログラムのエントリーポイント。val: 値が変更されない変数を定義。- メソッドの呼び出し。顧客情報を追加、全表示、条件付き表示を順に実行。
- サイト改善アンケート & ご指摘/ご質問
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などを アンケート 形式でお伺いしています。また記事の内容に関する ご指摘 や ご質問 もお待ちしています。


