#6 Kotlin Koans Introduction/Data classes 解説


1 はじめに

Kotlin公式リファレンスのKotlin Koans/Data classesの解説記事です。

Kotlin Koansを通してKotlinを学習される人の参考になれば幸いです。

ただし、リファレンスを自力で読む力を養いたい方は、
すぐにこの記事に目を通さないで下さい!

一度各自で挑戦してから、お目通し頂ければと思います

2-1 クラス定義・コンストラクタ

Kotlinではclassというキーワードをつけることでクラスを定義します。

クラス名の右横に()で囲んでコンストラクタを実装することができます。

コンストラクタは、クラスをインスタンス化するのと同時に呼ばれる関数のことです。

コンストラクタには2つの働きがあります。

・ プロパティを定義すること。

・ クラスのインスタンス化とパラメータの初期値の設定を同時に行うこと。

クラス定義・コンストラクタの実装を実際のコードで確認してみましょう。

//クラス定義。Invoiceがクラス名。
class Invoice { /*...*/ }   

//空のクラスの定義。クラス名の後の{]は省略できる。
class Empty          

//コンストラクタの実装。PersonクラスにfirstNameというプロパティを定義し、
//Personクラスがインスタンス化されるときに、firstNameに値が代入される。
//constructorというキーワードは省略できる。
class Person constructor(firstName: String) { /*...*/ }   

2-2 データクラス

クラスを定義する際、classのまえにdata修飾子を加えることで、クラスをデータクラスとして定義することができます。

データクラスは、

equal()関数、hashCode()関数、toString()関数、componentN()関数、copy()関数を自動的に実装してくれます。

2-3 セッター・ゲッター

Javaを学習された方には馴染みが深いかと思いますが、Kotlinにもゲッター・セッターが存在します。

ゲッター・セッターとはどちらも関数の1種です(Javaではメソッドと言います)。

Javaではクラス外からプロパティ(Javaではフィールドと言います)に値をセットするときにセッターを、クラス外からプロパティを利用したいときにゲッターを利用します。

ただ、Kotlinではこれら2つの関数を定義しなくても、暗黙的に定義されています。

なので特に何も定義しなくても、クラス外から目的のクラスのプロパティに値をセットしたり、利用したりできるのです。

実際にKotlinでクラス外でプロパティを利用しているコードを見てみましょう。

fun usePersonInfo(){
  //Personクラスのインスタンスを生成。
 val p = Person()
  //Personクラスのプロパティnameとageに値を代入。
  p.name = "名前"
 p.age = 20
 //プロパティnameとageの値を変数nとaに代入。
 val n = p.name
  val a = p.age
}

//Personクラスを定義しプロパティnameとageを作成。初期値として、空文字と0を代入。
class Person{
  var name : String = ""
  var age : Int = 0
}

やさしいKotlin入門(株式会社カットシステム)を参考にさせていただきました。)

3 Introduction/Data classesの解説

Kotlin Koans Introduction/Data classesの解説です。
随時本サイトの内容を引用させていただきます。

右側の本文を見てみましょう。

Rewrite the following Java code to Kotlin:

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Then add a modifier data to the resulting class. This annotation means the compiler will generate a bunch of useful methods in this class: equals/hashCode, toString and some others. The getPeople function should start to compile.

Read about classes, properties and data classes.

JavaのコードをKotlinで書き換えなさい。
そのとき、data修飾子を追加しなさい。これにより、コンパイラはdata修飾子のついたクラスに便利な関数を生成する(equal()関数やhashCode()関数、toString()関数など)。getPeople関数はコンパイルし始めるべきである。


Javaのコードを見てみましょう。

Personクラス内には、String型のプロパティnameとInt型のプロパティageが存在しています。

Person()関数によってクラス外からプロパティに値がセットできます(この関数がJavaのセッターです。)。

getName()関数とgetAge()関数によってクラス外からプロパティが利用できます(この関数がJavaのゲッターです。)。

これをKotlinで書き換えます。

class Person

このコードに加筆して、以下の3点を加えます。

  1. プロパティnameとage
  2. ゲッター
  3. セッター

ただし、Kotlinではゲッター・セッターは定義不要なので、
1.のプロパティnameとageの定義のみ行えばOKです。

プロパティをクラス内で定義するには、コンストラクタを利用するor利用しないの2通りあります。

ただ、getPeople()関数の中身を見てみると、

Person("Alice", 29), Person("Bob", 31)

Personクラスのインスタンスを生成すると同時に、引数を設定しています。

この引数はコンストラクタに渡されPersonクラスのプロパティの初期値になります。

なので今回はプロパティの定義にコンストラクタを利用しないといけません。

また、data修飾子を追加するように問題文に指定があるので、

data class Person(val name : String,val age : Int)

のようにすれば良いです(valはvarでもOKです。)。


(参考)

Personクラスの定義をdata修飾子無しでするとどうなるのでしょう?

Runボタンを押して見ると、

Fail: testListOfPeople: expected:<[Person[(name=Alice, age=29), Person(name=Bob, age=31)]]> but was:<[Person[@726f3b58, Person@442d9b6e]]>

というエラーメッセージが出ます。

これは、Person(name=Alice,age=29)とPerson(name=Bob,age=31)を期待していたのに、

Person@726f3b58とPerson@442d9b6eなんだけど、、、。といったニュアンスのメッセージです。

実は、dataクラスはtoString()関数を
インスタンスのプロパティの情報を人間のわかるように表示するように実装します。

以下で具体例を見てみましょう。

通常のクラスを用いた場合

fun showExample(){
  val e = Example("例1","例2")
 println(e.toString())
}

class Example(val ex1 : String,val ex2 : String)

これを実行すると、Person@gen37232と表示されます(@以下は任意の英数字の羅列です)。
Exampleクラスをdataクラスに書き換えて見ましょう。

dataクラスを用いた場合

fun showExample(){
  val e = Example("例1","例2")
 println(e.toString())
}

data class Example(val ex1 : String,val ex2 : String)

これを実行すると、Person(ex1=例1,ex2=例2)と表示されます。

また、toString()を省略しても同様の結果になります。

これだとPersonインスタンスのプロパティの情報が理解できますね。


4 最後に

次回はKotlin Koans Introducion/Nullable typesの解説をします