元Web系エンジニアのごはんブログ

JavaとかKotlinとかのごはん関係のブログです。

KotlinのlateinitでJavaFXが捗る

*最近*Kotlinに遅延初期化プロパティがあることを知りました。

taro.hatenablog.jp

遅延初期化プロパティはドキュメントから引用すると、

通常、非null型として宣言されたプロパティは、コンストラクタ内で初期化される必要がある。
しかし、これはかなり不便である。例えば、プロパティが依存オブジェクト (dependency injection 訳注:参考)により初期化されたり、ユニットテストのセットアップメソッドで初期化されたり。
この事例では、非nullイニシャライザをコンストラクタ内で提供することができないが、それでもクラス内の本体にあるプロパティを参照する際にnullチェックを避けたいであろう。
このような事例を処理するには、プロパティを lateinit 識別子でマークすることができる

http://qiita.com/dogwood008/items/6e8d3225ea9bb0fe3099#%E9%81%85%E5%BB%B6%E5%88%9D%E6%9C%9F%E5%8C%96%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3

これを使うことで、JavaFXコンポーネントを非nullとして扱えます。

まず、lateinitを使用しない場合は次のようなコードになります。

class SampleController : Initializable {
    @FXML
    var button: Button? = null

    @FXML
    var label: Label? = null

    @FXML
    fun onActionButton() {
        label!!.text = "テスト"
    }

    public override fun initialize(location: URL?, resources: ResourceBundle?) {
    }
}

コンストラクタ内でButtonオブジェクトを確実に初期化しなければならず、またコンストラクタ実行時の段階では値が定まらないため、null許容型にし、さらに値自体もnullで初期化しなければなりません。そのため、ボタンが押された時のonActionButtonメソッドで、label!!.text = "テスト"のように!!をつけてプロパティやメソッドを呼び出す必要がありました。

しかし、lateinitを使用すると、次のように書くことができます。

class SampleController : Initializable {
    @FXML
    lateinit var button: Button

    @FXML
    lateinit var label: Label

    @FXML
    fun onActionButton() {
        label.text = "テスト"
    }

    public override fun initialize(location: URL?, resources: ResourceBundle?) {
    }
}

このように!!を使わずにすっきりと書くことができます。