おはようエンジニア

まともなエンジニアになりたい

『Kotlinイン・アクション』第6章を読む (その2)

前回に続き、第6章「Kotlinの型システム」です。 後編はプリミティブ型と基本的な型に関する内容です。

『Kotlinイン・アクション』第6章を読む (その1) - おはようエンジニア

プリミティブ型の扱い

  • Javaの場合
    • プリミティブ型(intなど)と参照型(Stringなど)が区別される
    • コレクションのためにラッパークラスが必要になる
int num = 10;  // プリミティブ型
List<Integer> list = new ArrayList<>();  // 参照型であるラッパークラスが必要
  • Kotlinはプリミティブ型と参照型(ラッパークラス)の区別はない
    • null許容性によって変換先が変わる
      • null非許容型Javaのプリミティブ型に変換される
      • null許容型Javaのラッパークラスに変換される
num: Int = 10;  // 通常の型 (Javaのプリミティブ型に相当)
list: List<Int> = listOf();  // 通常の型 (Javaの参照型ラッパークラスに相当)

特殊な型

Any型

  • Any型 はKotlinのnull非許容型の最上位型
    • JavaではObjectにコンパイルされる
    • toString, equals, hashCode の3つのメソッドを持っている

Unit型

  • Unit型 は戻り値がない関数の戻り値に使う型
    • Javaの void と同じ機能だが以下が異なる
      • ジェネリクス関数の型引数として使える
      • 値を持ち、returnを書かなくても暗黙的に値 Unit を返す

Nothing型

  • Nothing型 は値を返さないことを示すときに使う型
    • Unitと同じく型引数として使えるが、値を返さない
    • 関数が正常に終了しないことをコンパイラに伝えることができる
fun fail(message: String): Nothing {
    throw IllegalStateException(message)
}

コレクションの型とインターフェイス

型引数のnull許容性

  • 型引数もnull許容性を持つ 例: List<Int?>
  • 変数自身と型引数のnull許容性に注意
    • List<Int?> : 「Int または null」 のリスト
    • List<Int>? : Int の「null を許容するリスト」

読み取り専用とミュータブルインターフェイス

  • コレクションは Collection インターフェイスを実装している
  • MutalbeCollection は Collection を継承している
  • 原則としてできる限り読み取り専用インターフェイスを使う
    • どこでデータが変更されるのかを理解しやすくなる
  • 読み取り専用コレクションは必ずしもイミュータブルではない
    • 別のコードによって参照先が変更される可能性がある

コレクション生成関数

タイプ 読み取り専用 ミュータブル
List listOf mutableListOf, arrayListOf
Set setOf mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf
Map mapOf mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf

Kotlin->Javaの注意点

  • Javaのコレクションはすべてミュータブル扱い
  • Javaコードにコレクションを渡す場合、Kotlin側でデータの変更を防ぐ仕組みはない

Java->Kotlinの注意点

  • Javaのコードはnull許容性の情報を持っていないのでKotlinではプラットフォーム型になる (前回記事参照)
    • null許容/null非許容 どちらとしても扱える
  • さらにJavaのコレクションは変更可能性の情報も持っていない
    • 読み取り専用/ミュータブル どちらとしても扱える
  • 以下の3つの条件で判断してKotlinコードの実装者が型を決める
    • コレクション自身がnull許容か
    • コレクションの要素がnull許容か
    • メソッドがコレクションを変更するか

配列

  • 基本的にKotlinでは配列ではなくコレクションを使用すべき
  • Array クラスはJavaの配列にコンパイルされる
    • 型パラメータを持つ (Array<Int>など)
    • コレクションと同様のメソッドをサポートしている
  • 生成には以下ような方法がある
    • arrayOf : 要素を明示的に渡して配列を生成する
    • arrayOfNulls : 上記のnull許容版
    • コンストラクタ : ラムダを渡して要素を初期化する
    • toTypedArray()でコレクションから配列に変換できる

プリミティブ型の配列

  • 配列の型引数はオブジェクト型扱い
    • Kotlinの Array<Int>JavaInteger[]
  • プリミティブ型の配列は専用のクラスを使う
    • Kotlinの IntArrayJavaint[]

まとめ

Kotlinではプリミティブ型のことを意識しなくてもパフォーマンスの問題がないように変換されることが分かりました。 その一方で、null許容性とコレクションの変更可能性についてはよく意識してコードを書く必要がありそうです。

これで Kotlinイン・アクション 第1部「Kotlinを知る」は終了です。第2部は「Kotlinを愛でる」で、自分でAPIを作成するためのより詳細な機能や仕様について記載されています。まとめ記事は一旦ここまでとして、以降は気が向いたら書く方針で行こうと思います。

Kotlinイン・アクション の感想

本書はプログラミング言語の本によくある、簡単な言語仕様(演算子など)から順番に書かれているような解説本と違い、読者の気になるところを先取りしてうまく興味を惹くような構成になっており、読み物のように飽きずに読み進めることができました。

内容はかなりJava開発者目線なものになっていますが、私のように普段Javaをゴリゴリ書かない人でも読むことできるように思います。読んでいると実際にコードを書いて試したいと思わせる良書です。