Android

Kotlinで初期化を遅延する

投稿日:2018年11月15日 更新日:

はじめに

こんにちは、前回に引き続き、Kotlinの基本的な文法をまとめています。今回はKotlinにおける初期化の遅延についてとなります。
by lazylateinitといったキーワードを初めて目にした時は「呼び出される時に初期化されるのね」という理解(間違いではないのですが言葉足らずでした)しかしておらず、改めて調べることでそれぞれの差異や機能の意図などを掴んでいこうと思います。

初期化の遅延とは

HaskellやScalaでは「遅延評価」と呼ばれているようです。
今回の記事では「インスタンス生成後にプロパティの値を定義できる」という意味で初期化の遅延という表現を使っています。
以下の記事で大まかな概要を理解できましたので、リンクを掲載しておきます。サンプルコードはScalaですが、概ね理解できると思います。
遅延評価とは何か

by lazy

  • 型は何でもOK
  • 一度だけ値の初期化を行う
  • 値はキャッシュされ、二回目以降は最初の値を常に返す
  • readonly

最後の「readonly」が注意点なのですが、これは後述します。
by lazyの記述方法は以下のようになります。by lazyの後にラムダ式が記述でき、その中で行われた処理の結果を値として、プロパティmsgが初期化されています。

「常に同じ値を返す」という性質なので、findViewByIdで取得したViewを入れたりすると、少し厄介なことになります。
というのも常に同じ値を返すため、例えばtextView.text = newValueなどとしても変更が反映されません。これはKotlinでは有名なアンチパターンとのこと。
参考: FragmentでKotlinのby lazyを使ってfindViewByIdするとレイアウト反映できない&リークする件
処理が進むにつれて変更されていく値は、次に紹介するlateinit, あるいはDelegates.notNullを使います。

lateinit

  • プリミティブ型は不可
  • val不可、varのみ
  • nullable不可
  • private推奨(初期化が行われる前に外部からアクセスされるのを防ぐため?)

「あとで必ず初期化するけど、インスタンス生成時にはできない」という時に使用します。必ず初期化するのでnon-nullで扱うことが可能となります。
またval不可なので、変更されることが前提となります。ActivityやFragmentのonCreate, onCreateViewで、findViewByIdで取得したViewなどが入ることを想定しているようです。
サンプルコードは下記のようになります。プロパティで変数名だけ宣言する場合、Javaでは値がnullになりますが、lateinitを付けてonCreate内で初期化すればnon-nullとして扱えます。

Delegates.notNull

Delegates.notNullはプリミティブ型に使えます。プロパティにアクセスする前に値をセットする必要があるため、下記のコードはコンパイルエラーとなります。

下記のようにsample.nonNullMsgに値を定義してから呼び出しましょう。

ここで「何のためにDelegates.notNullがあるんだろう、lazyかlateinitでいいんじゃないの」という疑問が湧いたのですが

  • lazyは値が不変な場合に使う
  • lateinitはプリミティブ型に使えない

という特徴があったのでした。Delegates.notNullは「可変かつnon-nullな値の初期化を遅延したい」時に使うのが良さそうです。
lazyinitとnotNullの使い分けについてはこちらが参考になりました → Kotlin : ‘notNull delegate’ vs ‘lateinit’

さいごに

いかがでしたでしょうか。「プロパティでnon-nullを保ちつつ、コードの途中で初期化したい。なるべくスマートな書き方で」となると、今回挙げたような記法が一例になると思います。
また、こういった記法を知っていることで、コードの書き手の意図を汲みやすく、また読み手に自分の意図を伝えやすくもなります。
「書きやすく、読みやすい」コードはなかなか難しいですが、常に意識しておきたいです。

おすすめ書籍

Kotlinスタートブック -新しいAndroidプログラミング Kotlinイン・アクション 速習 Kotlin: Javaより簡単!新Android開発言語を今すぐマスター 速習シリーズ

page_footer_300rect




page_footer_300rect




-Android
-

執筆者:


comment

メールアドレスが公開されることはありません。

CAPTCHA


関連記事

[Android] Firebase ML Kit勉強会に参加してきました

1 はじめに2 Firebase ML Kitとは3 準備するもの4 動かすまでの手順4.1 gradleのsyncがうまくいかない場合5 テキスト認識を試してみる6 画像のラベル付けを試してみる7 ...

はじめてのKotlinとAndroid StudioのKotlinプラグイン

1 はじめに2 Kotlinとは?3 Android Studio 2.3でのKotlinプラグイン導入3.1 Kotlinプラグインのインストール3.2 JavaコードをKotlinコードに変換3. ...

Kotlinのスコープ関数を調べて見た

1 はじめに2 スコープ関数とは3 スコープ関数の種類について4 with関数4.1 使い方4.1.1 withを使わない場合4.1.2 withを使う場合4.2 所感5 apply関数5.1 使い方 ...

[Android] パーミッション管理を簡単・簡潔に書けそうなPermissionsDispatcher

1 はじめに2 環境3 導入4 Activityでの実装例5 @RuntimePermissions(必須)6 PermissionsDispatcherに処理を移譲する7 @NeedsPermiss ...

Android Studioでエラーログを詳細表示する

1 はじめに2 初期設定でのビルドエラーメッセージ3 詳細なビルドエラーメッセージを出力4 おまけ5 さいごに6 おすすめ書籍 はじめに こんにちは。Android開発を久しぶりにやっているのですが、 ...

フォロー

follow us in feedly

page_side_300rect

2018年11月
« 10月 12月 »
 123
45678910
11121314151617
18192021222324
252627282930 

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。