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_responsive




-Android
-

執筆者:

         

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

【kotlin】CameraXでAndroidカメラを実装してみた

1 はじめに2 概要3 使用前の準備4 ViewFinderLayoutを実装する5 Camera Permissionのリクエスト6 カメラ撮影機能を実装する6.1 Previewクラスの実装6.2 ...

AndroidでWebViewを使用するときに気をつけたいポイント追加4選!

1 はじめに2 Cookie2.1 Cookieを設定する2.2 Cookieを取得する3 ハンドリングの効かないページ遷移3.1 POSTでのページ遷移3.2 PDFなど、WebViewで開くことの ...

Kotlinをはじめよう〜Kotlin基本文法〜

1 はじめに2 事前準備3 基本データ型4 変数5 条件分岐 if式6 条件分岐 when式7 繰り返し制御 while文8 繰り返し制御 for文9 さいごに10 おすすめ書籍 はじめに こんにちは ...

【Kotlin】Glideで角丸の画像を作成する

1 はじめに2 使用するライブラリのインポート3 Glideで画像を読み込む4 オプションまとめ5 さいごに6 おすすめ書籍 はじめに こんにちは。miyagawaです。 今回はGlideを使って角丸 ...

Android 11でdeprecatedになったAsyncTask対応Kotlin編

1 はじめに2 基本的な対応2.1 対応後のサンプル3 Coroutinesで実装4 最後に5 おすすめ書籍 はじめに 以前の記事で、Android 11にてdeprecatedになったAsyncTa ...

フォロー

follow us in feedly

blog-page_side_responsive

2018年11月
 123
45678910
11121314151617
18192021222324
252627282930  

アプリ情報

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