Kotlin のクラス

Kotlin のクラス定義についてまとめていく。

(プライマリ) コンストラクタとプロパティ

Kotlin のコンストラクタ定義は簡単で、たとえば次のように書ける。

class Person(firstName: String)

これだけで Person クラスと、そのコンストラクタを定義できる。しかし、これだけではコンストラクタは文字列 firstName を受け取るものの、オブジェクトの生成時に捨てられてしまう。

firstName を外からアクセス可能にするためには、次のようにすればよい。

class Person(firstName: String) {
    val firstName = firstName
}

これで、次のようにして firstName に外からアクセス可能になる。

val person = Person("MyFirstName")
println(person.firstName) // MyFirstName

同じ内容を次のように簡潔に書くこともできる。

class Person(val firstName: String)

Kotlin には data という修飾子があり、データを保存するためのクラスに使われる。 data 修飾子をつけると、Kotlin コンパイラが自動的に次のメソッドを実装してくれる。

  • equals()hashCode()
  • (読みやすい形式の) toString()
  • componentN() (N は整数: e.g. component1() は1番目のプロパティを返す)
  • copy()

これらのメソッドの詳細は公式ドキュメントに譲る

data を使う場合、コンストラクタで受け取る引数に valvar の指定が必須になる。先ほどと同じ内容を data class として書き直すと次のようになる。

data class Person(val firstName: String)

セカンダリコンストラクタ

コンストラクタは単なるクラス定義なので、オブジェクト生成時に実行するコードを記述できない。オブジェクトの生成時にコードを走らせたい場合は、init ブロックの中に書く。

class Person(val firstName: String) {
    init{
        // インスタンス作成時に実行される。
    }
}

なお、ここまで単に「コンストラクタ」と呼んできたものには、実は「プライマリコンストラクタ」という名称がある。プライマリと言うくらいなので、セカンダリコンストラクタというものもある。セカンダリコンストラクタを使い、オブジェクトの生成時にコードを実行することもできる。

次のコードを眺めてみよう。

class Person {
    constructor(param: String) {
        println("I'll be called when I'm instantiated.")
    }
}

public fun main(args: Array<String>) {
    Person("MyFirstName")  // "I'll be called when I'm instantiated."
}

constructor(...) の部分がセカンダリコンストラクタだ。このコードで “I’ll be called when I’m instantiated.” という文字列を出力できる。

プライマリコンストラクタとセカンダリコンストラクタの両方が定義されている場合、セカンダリコンストラクタはプライマリコンストラクタを this で呼ぶ必要がある。次のように書く。

class Person(val myFirstName: String) {
    constructor(param1: String, param2: String): this(param1) {  // プライマリコンストラクタに param1 を渡している
        println(param2)
    }
}

public fun main(args: Array<String>) {
    val person = Person("MyFirstName", "MySecondName")
    println(person.myFirstName)
}

継承

親クラスを明示的に指定しないクラスは Any の子クラスになる。

明示的に親クラスを指定するには、クラス定義の末尾に : BaseClassName(...) と書く。次に具体的な例を示す。

open class Base(p: Int)

class Derived(p: Int) : Base(p)

public fun main(args: Array<String>) {
    val derived = Derived(5)
}

これで Derived クラスは Base クラスを継承できる。 Base クラスの先頭にある open は、このクラスが継承可能であることを示している。 Java では final をつけない限りは全てのクラスが継承可能である。 Kotlin はその逆で、 open をつけない限りは全てのクラスで継承を許可しない。公式ドキュメントによると、これは Effective Java の “Design and document for inheritance or else prohibit it” の項に由来するポリシらしい。

広告

コメントを残す

コメントを投稿するには、以下のいずれかでログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中