Kotlinでクラス固定値を持つプロパティを作る時は「カスタムゲッター」を使うと良さそう

Kotlinでこんな感じの記述を見つけました。
「プロパティ宣言」と「カスタムゲッター付き宣言」で何が違うのかさっぱり分かりません。

class Moge {
    val one: Boolean = true       // 普通のプロパティ宣言
    val two: Boolean get() = true   // カスタムゲッター付き
}

oneにはデフォルト値ありで、twoにはない・・・?
パッと見だとget()以外同じでよく分からない。

さて、クラス固定の値(Boolean)を返すプロパティを定義する時、どちらが好ましいでしょう?

プロパティやらゲッターセッターやらの復習を兼ねてコードを見ていきます。

スポンサーリンク

環境情報

kotlin_version = '1.3.31'

プロパティ宣言

まず、下記のようなプロパティ宣言でプロパティを作成するとします。

class Moge {
    val one: Boolean = true
}

すると、私達の知らぬ間に内部的に

「フィールド(メンバ変数)」と「ゲッター」

が作られています。
今回はvalで宣言しましたが、varだと「ゲッター&セッター」が作られます。

これによってプロパティの値を参照したり代入したり出来ます。

class Moge {
    val one: Boolean = true
}

fun main() {
    Moge().one
    Moge().one = false // varの時のみ
}

Javaに変換して確認する

まだイマイチ分かりづらいのでJavaに変換してみます。
IntelliJ IDEAを使うと、

「Tools」 -> 「Kotlin」 -> 「Show Kotlin Bytecode」 -> 「Decompile」

で、簡単に変換することが出来ます。

Kotlin

class Moge {
    val one: Boolean = true
}

Java

public final class Moge {
   private final boolean one = true;  // 1. フィールドが作られている。

   public final boolean getOne() {    // 2. ゲッターが作られている。
      return this.one;                // 3. ゲッターを通してフィールドにアクセスしている。
   }
}

こんな感じです。だいぶ分かりやすくなりました。
ゲッターを通してフィールドの値を返してるということですね。

ではカスタムゲッター付きも同じく見てみましょう。

カスタムゲッター付きプロパティ

まず最初にリファレンスのサンプルコードを見てましょう。

val isEmpty: Boolean
    get() = this.size == 0

要するにゲッターを通してフィールドにアクセスする際、他の計算処理を挟むことが出来るようにする使い方のようです。

しかし、これだけでは一番最初のコードの疑問が解決されません。

class Moge {
    val one: Boolean = true     // 普通のプロパティ宣言
    val two: Boolean get() = true // カスタムゲッター付き
}

何故なら返しているのはどちらも trueだからです。
果たして何が変わるのでしょう?変換してみてみます。

Javaに変換して確認する

Kotlin

class Moge {
    val one: Boolean get() = true
}

Java

public final class Moge {
   public final boolean getOne() {
      return true; // フィールドが存在せず、ゲッターでフィールドを介さないでtrueをreturn。
   }
}

ここで違いがようやく分かりました。
カスタムゲッターを作成すると、フィールドが作成されていません。

つまり、

「インスタンス毎にフィールドは作られず、ゲッターを呼ぶだけで値が返せる」

固定の値を返したいのであれば、無駄なフィールドを作らないこちらが便利そうです。

まとめ

「クラス固定の値」を返すプロパティを作るならカスタムゲッターを使った記述が便利

ちなみに、この記述はエラーになります。

class Moge {
    val one: Boolean = true // NG: フィールドが作成されないので初期値をセットできない。
        get() = true
}

varで宣言すれば行けたりする

class Moge {
    var one: Boolean = true // OK: デフォルトセッターがあるのでフィールドに初期値をセットできる。
        get() = true
}

参考サイト

Properties and Fields/kotlinlang.org

13日目:プロパティとフィールド/Kotlin Advent Calendar 2012 (全部俺) JavaプログラマのためのKotlin入門