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開発言語を今すぐマスター 速習シリーズ

blog-page_footer_336




blog-page_footer_336




-Android
-

執筆者:


comment

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

CAPTCHA


関連記事

【Java】スレッドについてまとめてみました

1 はじめに2 スレッドの基本について3 スレッドの利用4 Threadクラス5 Runnableインターフェース6 同期処理7 synchronized修飾子8 おわりに9 おすすめ書籍 はじめに ...

Android JavaでS3への画像アップロード

1 はじめに2 AWS上での事前準備3 Android StudioのGradleでAWS SDKをインストール4 ManifestにPermissionの追加5 カメラで写真を撮影し、保存先のPat ...

GoogleMap Clusterのカスタマイズ

1 はじめに2 クラスタ内のアイテムクラス3 クラスタをレンダリングするクラス4 クラスタの色を設定する5 クラスタ化の最小個数を設定する6 クラスタのクリックイベントを拾う7 さいごに はじめに 最 ...

【Androidマテリアル】Ripple Effect

1 はじめに2 Ripple Effectとは3 設定方法4 カスタマイズ5 さいごに はじめに こんにちは、ソニーから新Aiboが発表されましたね。個人的には欲しいと思っているのですが、最近Goog ...

【Kotlin】FirebaseAuthenticationでメールアドレスで認証機能を実装

1 はじめに2 レイアウト3 新規登録4 ログイン5 さいごに6 参考7 おすすめ書籍 はじめに こんにちは。miyagawaです。 前回は「FirebaseAuthenticationでGoogle ...

フォロー

blog-page_side_responsive

2018年11月
 123
45678910
11121314151617
18192021222324
252627282930  

アプリ情報

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