data class入門
今回はdata classの話をします。 クラスの話はもうちょっと後にするつもりなのだけど、とりあえずdata classは使いたいのでdata classの簡単な使い方を先に。
Data classes - Kotlin Documentation
data class入門
data classは、複数のデータをまとめて持つのに使う機能です。 割と単純なので特に難しい事も無いのですが、実際に使う所を見ないと「なんでそんな機能あるの?」って思って終わりだと思うので、 ここまで登場しませんでした。
でも今回、ListViewの編集とDateの説明が終わったので、ようやく具体的な使い道をもとに説明出来ます。
という事で、まずは使い道から見ていきましょう。
前回の日付の所でやった「ListViewに挑む!編集編」に、投稿時間をつける所のリストがいまいち
data classを使いたくなるシチュエーションとして、日付を扱う、Date入門の最後でやった、課題: 「ListViewに挑む!編集編」に、投稿時間をつける のリストの所を考えます。
上記のリンク先では、以下のようにしました。
val listData = mutableListOf<String>()
val listDt = mutableListOf<Date>()
でもこの二つは毎回セットでaddされるし、セットでlistData[position]
とlistDt[position]
されます。
消す時も両方同じ所を消さないといけません。
こういうのはいかにも片方操作し忘れとかがあってバグりやすい。
そこでStringとDateをまとめて一つの要素としてListに追加していくのが良い解決策です。 それを実現するのがdata classです。
以下data classの具体例を見ていきましょう。
data classの簡単な例
まずdata classの例を見ていきたいと思います。
data class は以下のように使います。
以下、細かく見ていきましょう。
data classの文法
まずdata classは最初にdata class クラス名
で始まります。
クラス名は大文字始まりで単語の区切り大文字という慣習になっています。
つまりTwoIntとかUserDataとかそういうものになります。
そしてクラス名
の後にカッコが続き、変数定義のようなものが、型付きで並びます。
代入する場合はvar、代入しない場合はvalですが、あまりvarを使う事は無いのでvalとおぼえてしまっても良いでしょう。
こうしてdata classが定義出来ます。data classは、新しい型となります。この場合はTwoInt型が出来る事になります。
次に使い方です。data classは定義すると、そのクラス名を関数のように使う事が出来て、
そのreturnはそのdata classのデータとなります。先ほどの例ではTwoInt
というのを関数のように使う事が出来て、
TwoInt(1, 2)
とすると、TwoInt型のデータが作れる訳です。
各構成要素の触り方はドットと変数名
さて、val ti1 = TwoInt(1, 2)
とti1変数にデータを入れられました。
この1とか2にはどうアクセスするか?というと、ti1.v1
とかti1.v2
というように、
ドットとdata classを定義した時の変数名でアクセスします。
これで基本的な使い方は終わりです。 ちょっと幾つか例とか練習問題とかを見ていきましょう。
data classを使った例いろいろ
幾つか例を見ていきましょう。さきほどはどっちもIntだったので、次はStringとIntの例を。 ユーザー名とスコアを持たせる、というのは割と良くあります。
また、これをListに入れる事もできる。
次に「ListViewに挑む!編集編」で、入力されたテキストが追加された時間をDateで保存するような場合を考える。 Dateなのでimport文を追加して、以下のような感じになる。
では自分でも幾つか作ってみましょう。
課題: ユーザー名と投稿数を持つ、SNSUserを作れ
ユーザー名はname, 投稿数はpostNumとしましょう。
課題: 名前と攻撃力と防御力を持つCharacterを作れ
名前はname, 攻撃力はattack、防御力はdefenseとしますか。
課題: アイテムをたくさん持つアイテムボックスのdata classを作れ
アイテムボックスは名前がnameであって、Stringのアイテムをたくさん持つとします。とりあすList<String>
でitemsという名前でいいでしょう。
課題: 以下をtrueになるように変更せよ
要素にアクセスする方もやってみます。
課題: 前回の日付の入門でやった、「ListViewに挑む!編集編」に、投稿時間をつけたものをdata class化しよう
という事でdata classについての簡単な説明をしたので、ついに日付を扱う、Date入門の最後でやった、課題: 「ListViewに挑む!編集編」に、投稿時間をつける でリストが二つだった問題を、 data classを使ってもっといい感じにしましょう。
- Postというdata classを作り、項目名とDateをもたせる
- listDataをPostのMutableListにする
- getViewで時刻表示用TextViewに時刻をセットするあたりを修正
- アイテムを追加するボタンのsetOnClickListenerで、Postを追加するようにして、その時点でのDate()を持たせる
以下各ステップを見ていきましょう。
1. Postというdata classを作り、項目名とDateをもたせる
Postというdata classで、StringのitemとDate型のdateを持たせるとしましょう。 このPostというdata classは、コードの置き場所入門の「1番目の区画」に置きます。
ついに1番目の区画にコードを書く時が来ましたね。
ここでDateの所が赤くなったら、上にカーソルを移動して、Alt+Enterでimportを追加しましょう。
2. listDataをPostのMutableListにする
これは特に解説の必要は無いですかね。
3. getViewで時刻表示用TextViewに時刻をセット
itemLabelにセットしているのと同様に、itemDateにも日付をセットします。toStringでいいでしょう。
日付は、以下のような感じでセットします。
val item = listData[position]
view.findViewById<TextView>(R.id.itemDate).text = item.date.toString()
itemLabelの方もこんな感じで変更します。
4. アイテムを追加するボタンのsetOnClickListenerで、Postを追加するようにして、その時点でのDate()を持たせる
setOnClickListenerの中で、以下みたいな感じに書きます。
val text = findViewById(R.id.edit1).text.toString()
val post = Post(text, Date())
listData.add(post)
変数使わなくてもいいですが、このくらいは使った方が読みやすいとは思う。
以上で、二つのリストを同時に追加したり削除したり、という事が不要になりました。やったね!
まとめ: リストに二つ以上何か持たせたい時はdata classが便利
リストに、投稿された文字列と時間の二つを追加したい、みたいな時にはdata classが便利なので使っていきましょう。
おまけ:クラスの用語いろいろ
このシリーズはAndroid側とkotlin言語側の話が交互に続いていく感じになっていますが、 Android側の最難関はおそらくListViewです。
一方kotlin側の最難関はクラスとなります。
クラスは何が難しいって用語がめちゃくちゃ多い。 そこで割と単純なdata classの段階で用語を幾つか先取りしておきます。 現時点では次回予告の前にちょっと思わせぶりなクールなキャラが出てきて意味深な事言って次回に続くって感じだな、と思っておけばいいです。
クラスとオブジェクト(またはインスタンス)
data class TwoInt(val v1: Int, val v2: Int)
でTwoIntクラスという名前の型が出来ます。
そして、TwoIntクラスの型のデータをオブジェクトと呼びます。
少しややこしいですね。型とは何か?で少し触れたように、 型というのは、データのカテゴリでした。
ストII、ストIIダッシュ、スーパーストII、スパIIXなどがデータで、ストIIシリーズが型、というものでした。
つまり一つの型というカテゴリに対し、そのカテゴリにあてはまるデータが複数ある訳です。
そしてこのカテゴリにはInt
とかString
とかList<String>
とかがある訳だけれど、
今回新しくTwoInt
というカテゴリを作れるようになった訳です。
ストIIシリーズという型にはいろんなストIIのタイトルがあるように、
TwoIntというカテゴリにも、(1, 2)
というデータを持つTwoIntや、(8, 3)
を持つTwoIntなど、いろんなデータが存在します。
このデータを、クラスの時は「オブジェクト」とか「インスタンス」と呼ぶ事になっているという訳です。 「オブジェクト」と「インスタンス」はほぼ同じ意味です。起き昇とリバーサル昇竜くらいの違いです。
最初のうちはややこしいかもしれないけれど、クラスを自分で作っていくようになるとこのインスタンスとクラスの区別みたいなのは何度も出てくるようになるので、 使っていくと慣れます。
という事で我らもこれから使っていく事にする。
以上をまとめると、以下のようになります。
data class TwoInt(val v1: Int, val v2: Int)
でTwoIntクラスが出来るTwoInt(1, 2)
などと呼ぶと、TwoIntクラスのインスタンスが作れるTwoInt(7, 3)
などと呼んでも、TwoIntのクラスのインスタンスは作れる- 一つのTwoInt型からインスタンスはたくさん作れる
- TwoInt型とTwoIntクラスはほとんど同じ意味
とりあえず用語はややこしいので何度も使って慣れる方がいい。という事で以後バリバリ使っていきましょう。
メンバ変数v1, v2
先ほどの定義を再掲します。
data class TwoInt(val v1: Int, val v2: Int)
このv1とv2をメンバ変数と呼びます。 メンバ変数というのはこれまでもActivityの所に定義している変数をそう呼んでいました。 あれも内部的には全く同じものです。 クラスを真面目にやると両者が同じものなのが分かりますが、とりあえずここではdata classのこれらの変数もメンバ変数と呼ぶ、 とだけ覚えておいてください。