情報と電子とおおかた遊び

プログラムの備忘録を綴りつつ、適当に遊びも記載するゆるいブログ

Kotlinのいろは4

クラス

さぁて、とりあえずこれを一旦、基礎の最後にしようと思います。
内容はKotlinのクラスとその関連したものです。 クラスの概念とか、そういうのは今更話さないので、自主補完で宜しくです。

基本的なクラスの宣言

一旦ざっくりと、作成したクラスを下記に記します。 その後、解説が必要な部分は、書いていこうと思います。 結構、Kotlin特有の書き方とかが多いので、慣れるまで時間が掛かりそうな仕様です。

// Personクラス 引数として文字列を受け取る
//このカッコ部分ををKotlinではプライマリコンストラクタと呼ぶ(なくてもクラスの宣言は可能)
class Person(name: String) {

    // プロパティ(クラスのメンバ変数のようなもの)
    // プライマリコンストラクターで渡された値も使える(initで初期化する必要はない)
    public var name = name
    public var nameUpper : String= name.toUpperCase()
        set(value) {
            field = value.toUpperCase()
        }
        get() : String{
            return this.nameUpper
        }


    // インスタンス生成時に呼ばれる。
    init {
        ///クラス宣言のかっこの中の引数がここで使える
        println("Person initialized with value ${name}")
    }


    // セカンダリコンストラクタ
    // プライマリコンストラクターが存在するため、this()を呼び出し、その後の{}でそのほかの処理を書いている。 
    constructor(firstName: String, lastName: String):this("$firstName $lastName"){
        println("firstName = $firstName, lastName = $lastName")
    }


    // セカンダリコンストラクタ2
    // セカンダリコンストラクターはいくつでも宣言可能。
    constructor(firstName: String, lastName: String, middleName : String):this("$firstName $middleName $lastName"){
        println("firstName = $firstName, lastName = $lastName, middleName=$middleName")
    }


    // メンバ関数
    public fun introduceSelf() : Unit {
         println("My name is $name")
    }

    private fun shoutName(): Unit{
         println("$nameUpper!!!")
    }

    protected fun whichClass(): Unit{
         println("Person")
    }

    internal fun moduleName(): Unit{
         println("PersonModule")
    }

}

解説

プロパティ

クラスには、状態を表す値としてプロパティというものが存在します。 人によっては、クラスのメンバ変数とかフィールドといったほうがしっくりくる方もいるかもしれません。

Javaなどと共通しているところは、public/private/protected/internal(Kotlin特別仕様)と頭につけることで、 可視性を表せること。

違いとしては、値の取り扱いに介しての概念です。一般的にJavaを書いてる人なら、おそらくメンバ変数はprivateにしておき、 その値が取り出しても問題ない場合は、受け口と窓口として、setter/getterメソッドを用意していたと思います。 しかし、プロパティは宣言した時点で、データの受け口である、メンバ変数と対応したsetter/getterが自動で作られます。 下記にインスタンス化したPersonクラスのプロパティを、使ってみるクラスを記します。

fun main(args: Array<String>) {
    //インスタンス化
    var personInst : Person = Person("Big", "Back")

    //nameプロパティを取り出し、出力する。
    println("Property: name = " + personInst.name) // Property: name = Big Back

    //nameプロパティに値をセットする
    personInst.name = "Back Boom"
}

なんというか、クラスのメンバ変数の扱い方は、Pythonと似てますね。

また、変わり種なのが、"custom setter"/"custom getter"というものを宣言することもできます。 PersonクラスのnameUpper変数を見てください。変数の下にset(value)/get()と書かれている処理があると思います。 この部分はプロパティを取り出すときと、値を代入する際に宣言した処理が動きます。

get()は単純に値を返してるだけなので、実は宣言しなくてもいいのですが、今回は説明のためわざわざ、書いておきました。

set(value)は渡された値を、大文字変換しています。プロパティに代入するだけで、勝手に大文字になります。

下記が代入した際の処理と結果です

fun main(args: Array<String>) {
    //インスタンス化
    var personInst : Person = Person("Big", "Back")

    //nameプロパティに値をセットする
    personInst.nameUpper = "Back Boom"

    //nameプロパティを取り出し、出力する。
    println("Property: nameUpper = " + personInst.nameUpper ) // Property: name = BACK BOOM
}

コンストラクタ

Kotlinのコンストラクターも、これまた変わっているので、最初はぱっと見分からない場合が多いですね。

プライマリコンストラクタ

Personクラスですと、最初の宣言部分がすでにコンストラクタ、プライマリコンストラクタ、となります。 この時受け取る引数は、すぐ使えるようになるので、プロパティにすぐさま代入することができます。

さらにinitを追加することで、コンストラクタとは別に、インスタンス化時の初期化処理を追加することもできる。

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

Kotlinのクラスは、コンストラクタを複数持つことができる。 他の言語だと、”オーバーロード”で対応しているが、Kotlinは言語レベルで複数コンストラクタを想定しているらしい。

このセカンダリコンストラクタ、一つ注意がある。実は、クラス内にプライマリコンストラクタ存在する場合、 this()を呼んでプライマリコンストラクタを呼び出す必要がある(Personクラス参照)。そのうえで、セカンダリコンストラクタ独自の処理を、 書いていく必要がある。

まとめ

とりあえず、さらっとクラスについて書いていきました。 インターフェースや、抽象クラス、継承、などなど概念はあるのですが、 とりあえず、クラス概念までやれば、ある程度の開発ができるので、ここで区切ります。

実際に開発を開始して、備忘録が必要になったら、ここに書いていきます。

参照

Kotlinスタートブック -新しいAndroidプログラミング

Kotlinスタートブック -新しいAndroidプログラミング