Kotlinの入門

# Kotlin 入門

- [Kotlin Docs | Kotlin](https://kotlinlang.org/docs/home.html)
  - 参考
    - [リファレンス - Kotlin Programming Language](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/)
    - [今更聞けないKotlin Generics入門](https://zenn.dev/96mame/articles/21e2f8c95947e9581192)
    - [ジェネリクスの「制約」と「in/out」キーワード](https://pouhon.net/kotlin-constraints/3649/)

# Kotlinとは

- Kotlinとは、Javaの統合開発環境であるIntelliJ IDEAで有名なJetBrainsが開発したオブジェクト指向プログラミング言語
  - Groovy やScala から、機能や簡易記法（糖衣構文）を採用している
  - ジェネリクスの構文などでC#の影響を受けている 
  - 2012年2月14日、Kotlin はApacheライセンス バージョン2.0に基づいてオープンソース化された
  - 2019年、[Google](https://ja.wikipedia.org/wiki/Google)はKotlinをAndroidアプリケーション開発の標準にした
- 言語構文自体はJavaとは互換性がないが、コンパイルされたコードはJava VM上で動作するため、これまでのJava資産の多くを流用できる
  - Java JVMだけがターゲットでなく、JavaScript / Native コードの生成も可能である
- Java VMで動作する他のプログラミング言語
  - Groovy : https://groovy-lang.org/
  - Scala : https://www.scala-lang.org/
  - Clojure : https://clojure.org/
  - JRuby : https://www.jruby.org/
  - Jython : https://www.jython.org/
  - Ceylon : https://ceylon-lang.org/

# 基本

## エントリポイント

- `main` 関数がエントリポイントとなる

  ```kotlin
  fun main() {
      println("Hello world!")
  }
  
  // プログラム引数を取る場合
  fun main(args: Array<String>) {
      println(args.contentToString())
  }
  ```

## 標準出力

- `print` / `println` 関数を利用する

  ```kotlin
  print("Hello ")
  print("world!")
  
  println("Hello world!")
  println(42)
  ```

## 構文

### 関数の定義

- 2つの`Int`型の引数を持ち、`Int`型を戻り値とする関数
  
  ```kotlin
  fun sum(a: Int, b: Int): Int {
    return a + b
  }
  
  // 式本体と推論された戻り値の型
  fun sum(a: Int, b: Int) = a + b
  ```

- 値を返さない関数
  
  ```kotlin
  fun printSum(a: Int, b: Int): Unit {
    print(a + b)
  }
  
  // Unitは省略可
  fun printSum(a: Int, b: Int) {
    print(a + b)
  }
  ```

### 変数の定義

- 1度だけ代入できる（Immutable）ローカル変数
  
  ```kotlin
  val a: Int = 1
  val b = 1   // `Int`型が推論される
  val c: Int  // 初期値が与えられない場合、型指定が必要
  c = 1       // 明確な代入
  ```

- 変更可能 (Mutable) な変数
  
  ```kotlin
  var x = 5 // `Int`型が推論される
  x += 1
  ```

### null可能値を使用した、nullのチェック

- `null`値を取り得る場合、参照は明示的に`null`をチェックする必要あり
  
  ```kotlin
  // nullを返す可能性のある関数
  fun parseInt(str: String): Int? {
    // ...
  }
  
  // null可能値を返す関数を使用
  fun main(args: Array<String>) {
    if (args.size < 2) {
      print("Two integers expected")
      return
    }
  
    val x = parseInt(args[0])
    val y = parseInt(args[1])
  
    // `x`, `y`はnullが入っていることがあるので、`x * y`はエラーを引き起こす
    if (x != null && y != null) {
      // xとyは、nullチェックの後自動的に非null許容型へキャストされる
      print(x * y)
    }
  }
  
  // 別な例
  // null可能値を返す関数を使用
  fun main(args: Array<String>) {
    if (args.size < 2) {
      print("Two integers expected")
      return
    }
  
    val x = parseInt(args[0])
    val y = parseInt(args[1])
  
    if (x == null) {
      print("Wrong number format in '${args[0]}'")
      return
    }
    if (y == null) {
      print("Wrong number format in '${args[1]}'")
      return
    }
  
    // x and y are automatically cast to non-nullable after null check
    print(x * y)
  }
  ```

### 型チェックと自動キャストの使用（スマートキャスト）

- `is`演算子で型チェックを行う (Javaの`instanceof`に相当)
  
  - `is`で特定の型をチェックした後は、明示的なキャストが不要
  
  ```kotlin
  // 例1 : if内はStringとして参照
  fun getStringLength(obj: Any): Int? {
    if (obj is String) {
      // `obj` はこのブランチ内では自動的に`String`へキャストされる
      return obj.length
    }
  
    // `obj` は型チェックが行われたブランチ外では、まだ`Any`型である
    return null
  }
  
  // 例2 : ifの外側でStringとして参照
  fun getStringLength(obj: Any): Int? {
    if (obj !is String)
      return null
  
    // `obj` はこのブランチ内では自動的に`String`へキャストされる
    return obj.length
  }
  
  // 例3 : 遅延評価演算子 && とif内ではStringとして参照
  fun getStringLength(obj: Any): Int? {
    // `obj` は`&&`の右側では自動的に`String`へキャストされる
    if (obj is String && obj.length > 0)
      return obj.length
  
    return null
  }
  ```

### 範囲

- `in`演算子で数値が範囲内にあるか判定（`!in`で範囲外を判定）
  
  ```kotlin
  // 範囲内の判定
  if (x in 1..y-1)
    print("OK")
  
  // 範囲外の判定
  if (x !in 0..array.lastIndex)
    print("Out")
  
  // forループでの使用
  for (x in 1..5)
    print(x)
  ```

## 基本型

### 数値

#### 型

##### 整数型

| Type    | Size (bits) | Min value                         | Max value                           |
| ------- | ----------- | --------------------------------- | ----------------------------------- |
| `Byte`  | 8           | -128                              | 127                                 |
| `Short` | 16          | -32768                            | 32767                               |
| `Int`   | 32          | -2,147,483,648 (-231)             | 2,147,483,647 (231 - 1)             |
| `Long`  | 64          | -9,223,372,036,854,775,808 (-263) | 9,223,372,036,854,775,807 (263 - 1) |

##### 浮動小数型

| Type     | Size (bits) | Significant bits | Exponent bits | Decimal digits |
| -------- | ----------- | ---------------- | ------------- | -------------- |
| `Float`  | 32          | 24               | 8             | 6-7            |
| `Double` | 64          | 53               | 11            | 15-16          |

#### リテラル定数

- 整数値のリテラル
  - 数値: `123`
    - `Long`型の数を表すには大文字の`L`でタグ付けする: `123L`
  - 16進数: `0x0F`
  - 8進数: サポートしない
  - 2進数: `0b00001011`
- 浮動小数のリテラル
  - デフォルトではdouble型: `123.5`, `123.5e10`
  - float型を表すには `f` or `F` でタグ付けする: `123.5f`

#### ボクシング

- JVMプリミティブ型として数値が物理的に格納されている
  
  - ジェネリクス・null許容型(例: `Int?`)が関与すると、ボクシングされる
  
  ```kotlin
  val a: Int = 10000 // プリミティブな数値
  print(a === a) // 'true'を出力する
  val boxedA: Int? = a // ボクシングされた数値
  val anotherBoxedA: Int? = a  // ボクシングされた数値
  print(boxedA === anotherBoxedA) // !!! 'false'を出力する !!! : === 参照等価評価
  print(boxedA == anotherBoxedA) // 'true'を出力する : 構造等価評価 (.equalsに該当)
  ```

#### 明示的な変換

- 小さな型は大きな型のサブタイプではない
  
  - 明示的な変換なしで、`Byte`型の値を`Int`型へ代入することができないことを意味する
  - 異なる型の算術演算においては、算出される型は推論される
  
  ```kotlin
  val b: Byte = 1
  val i: Int = b // エラー
  val i: Int = b.toInt() // OK
  
  val l = 1L + 3 // Long + Int => Long
  ```

- 全ての数値型は次の変換をサポートしている
  
  - `toByte(): Byte`, `toShort(): Short`, `toInt(): Int` , `toLong(): Long`, `toFloat(): Float`, `toDouble(): Double`, `toChar(): Char`

### 真偽値

- `Boolean`型は真偽値を表し、`true`  `false` の2つの値がある

### 文字

- 文字は、`Char`型で表され、数字として直接扱うことはできない
  
  ```kotlin
  fun check(c: Char) {
    if (c == 1) { // ERROR: 非互換の型
      // ...
    }
  }
  ```

- サポートされるエスケープシーケンス
  
  - `\t`, `\b`, `\n`, `\r`, `\'`, `\"`, `\\`, `\$`
  - Unicodeエスケープシーケンス: `\uFF00`

### 文字列

- 文字列は、`String`型で表される
  - 文字列は不変（イミュータブル）
  - 文字列の要素は、インデックスの演算でアクセスできる：`s[i]`

#### 文字列リテラル

- 2つの種類の文字列リテラル
  
  - エスケープされた文字列を持ちうるエスケープ済み文字列
    
    ```kotlin
    val s = "Hello, world!\n"
    ```
  
  - 改行と任意の文字を含む生文字列
    
    ```kotlin
    val text = """
      for (c in "foo")
        print(c)
    """
    ```
    
    - 先頭の空白を[`trimMargin()`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-margin.html)関数で削除する例
      
      - デフォルトでは`|`はマージンの接頭辞として使用されるが、`trimMargin(">")`のように、パラメータとして別の文字を渡すとそれを接頭辞として使用することができる
      
      ```kotlin
      val text = """
          |Tell me and I forget. 
          |Teach me and I remember. 
          |Involve me and I learn.
          |(Benjamin Franklin)
          """.trimMargin()
      ```

#### 文字列テンプレート

- 文字列はテンプレート式、すなわち、評価され、その結果が文字列と結合されるコードの断片を含むことができる
  
  ```kotlin
  val i = 10
  val s = "i = $i" // "i = 10"と評価される
  
  val s = "abc"
  val str = "$s.length is ${s.length}" // "abc.length is 3"と評価される
  
  // 生文字列内で $ を出力する例
  val price = """
  ${'$'}9.99
  """
  ```

## パッケージ

### パッケージ定義

- ソースファイルの先頭でパッケージを記述する。

- Javaとは異なり、ディレクトリとパッケージが一致する必要はない。
  
  ```kotlin
  package my.demo
  
  fun baz() {}
  
  class Goo {}
  ```

- `baz()`の完全名は`foo.bar.baz`であり、`Goo`の完全名は`foo.bar.Goo
  
  - パッケージが指定されない場合は、ファイルの内容は名前を持たない`default`パッケージに属することになる

### インポート

- 単一の名前を指定してインポート
  
  ```kotlin
  import foo.Bar // Barは許可無しでアクセス可能になります
  ```

- あるスコープ（パッケージ、クラス、オブジェクト等）内の全てのアクセス可能なコンテンツのインポート
  
  ```kotlin
  import foo.* // 'foo'内の全てがアクセス可能になります
  ```

- 名前の衝突がある場合、`as`キーワードを使用して衝突するエンティティを局所的にリネーム
  
  ```kotlin
  import foo.Bar // Barはアクセス可能
  import bar.Bar as bBar // bBarは'bar.Bar'を意味する
  ```

- Javaとは違って、Kotlinは`import static`構文を持っていない

## 制御フロー

### if式

- Kotlinでは、`if`は式であり、値を返す（`if`を文ではなく式として使用する（例えば値を返したり変数に代入したりする）ならば、その式には`else`分岐が必要）
  
  - 従って、三項演算子は存在しない
  
  ```kotlin
  // 伝統的な文としての使用
  var max = a 
  if (a < b) 
    max = b 
  
  // else付き
  var max: Int
  if (a > b) 
    max = a 
  else 
    max = b 
  
  // 三項演算子のように式として利用
  val max = if (a > b) a else b
  ```

- `if` の分岐はブロックにすることができ、最後の式がそのブロックの値となる
  
  ```kotlin
  val max = if (a > b) { 
      print("Choose a") 
      a 
    } 
    else { 
      print("Choose b") 
      b 
    }
  ```

### when式

- 文として利用した場合: `else`は必須ではない
  
  ```kotlin
  when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> {
      print("x is neither 1 nor 2")
    }
  }
  
  when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("それ以外")
  }
  ```

- 式として利用した場合: `else`は必須
  
  ```kotlin
  fun valueToString(value: Int) =
      when(value) {
          1 -> "One"
          2 -> "Two"
          else -> "Unknown value (value = $value)"
      }
  ```

- `in`または`!in`を使用すると、コレクションの [範囲 (range)](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/ranges.html) が可能
  
  ```kotlin
  when (x) {
    in 1..10 -> print("xは範囲内")
    in validNumbers -> print("xは有効")
    !in 10..20 -> print("xは範囲外")
    else -> print("どれにも該当せず")
  }
  ```

- 特定の型を検査するために`is`または`!is`を利用
  
  - [スマートキャスト](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/typecasts.html#smart-casts)の機能により、その型のメソッドやプロパティに追加のチェック無しでアクセスできることに着目
  
  ```kotlin
  val hasPrefix = when(x) {
    is String -> x.startsWith("prefix") // x は String へキャストされている
    else -> false
  }
  ```

### forループ

- `for`ループはイテレータによって提供されるものを繰り返し実行
  
  ```kotlin
  // ブロックなし
  for (item in collection)
    print(item)
  
  // ブロックあり
  for (item: Int in ints) {
    // ...
  }
  ```

- ライブラリ関数の`withIndex`を使用することで、要素のインデクスを取得する例
  
  ```kotlin
  for ((index, value) in array.withIndex()) {
      println("$indexの要素は$value")
  }
  ```

### whileループ

```kotlin
while (x > 0) {
  x--
}

do {
  val y = retrieveData()
} while (y != null) // y はここで可視(visible)
```

### returnとジャンプ

- Kotlinの3つの構造的ジャンプ演算子
  - `return`: デフォルトでは最近のクロージャ（関数閉包）や[匿名関数](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/lambdas.html#anonymous-functions)から抜け出す
  - `break`: 最も近い外側のループを終わらせる
  - `continue`: 最も近い外側のループを次のステップに進ませる

#### breakとcontinueのラベル

- Kotlinにおける任意の式を `label`でマークすることができる
  
  - ラベルは、 `@` 記号に続く識別子の形式をもつ:  `abc@` 、`fooBar@`が有効なラベル
  
  ```kotlin
  loop@ for (i in 1..100) {
    for (j in 1..100) {
      if (...)
        break@loop
    }
  }
  ```

#### ラベルに復帰

```kotlin
// 明示的なラベルを利用
fun foo() {
  ints.forEach lit@ {
    if (it == 0) return@lit
    print(it)
  }
}

// 暗黙のラベルを利用
fun foo() {
  ints.forEach {
    if (it == 0) return@forEach
    print(it)
  }
}
```

### 例外

#### 例外クラス

- Kotlinの例外は、`Throwable`のサブクラスとなる

  - Javaと異なりチェック例外はない

  ```kotlin
  // 例外のスロー
  throw MyException("Hi There!")
  
  // 例外のキャッチ
  try {
    // some code
  } catch (e: SomeException) {
    // handler
  } finally {
    // optional finally block
  }
  
  // try を式として利用する
  val a: Int? = try { parseInt(input) } catch (e: NumberFormatException) { null }
  ```

# クラスとオブジェクト

## クラスと継承

### クラス

- Kotlinでのクラスは、`class`キーワードを使用して宣言
  
  ```kotlin
  class Invoice {
  }
  
  // 本体がない場合は {} を省略できる
  class Empty
  ```

### コンストラクタ

- Kotlin内のクラスは、 **プライマリコンストラクタ** と1つまたは複数の **セカンダリコンストラクタ** を持つことがでる

#### プライマリコンストラクタ

- プライマリコンストラクタ: クラスのヘッダーの一部
  
  ```kotlin
  class Person constructor(firstName: String) {
  }
  
  // プライマリコンストラクタがアノテーション・可視装飾子を持たない場合 constructor キーワードを省略できる
  class Person(firstName: String) {
  }
  ```

- プライマリコンストラクタは、コードを含めることができない
  
  - 初期化コードは`init`キーワードを付与したブロック内に記述
  
  ```kotlin
  class Customer(name: String) {
      init {
          logger.info("Customer initialized with value ${name}")
      }
  }
  ```

- プライマリコンストラクタの引数を使用して、プロパティを初期化する例
  
  ```kotlin
  class Customer(name: String) {
      val customerKey = name.toUpperCase() // プロパティの宣言と初期化
  }
  ```

- プロパティの宣言と初期化をプライマリコンストラクタから行う例
  
  - プロパティはプライマリコンストラクタの中で可変値（ミュータブル） ( `var` ) または固定値（イミュータブル） ( `val` ) で宣言可能
  
  ```kotlin
  // コンストラクタの引数は、プロパティとして定義される
  class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
  }
  ```

- プライマリコンストラクタがアノテーションや可視性修飾子を持つ場合は、 `constructor` キーワードが必要
  
  ```kotlin
  class Customer public @Inject constructor(name: String) { ... }
  ```

#### セカンダリコンストラクタ

- セカンダリコンストラクタの宣言例
  
  ```kotlin
  class Person {
      constructor(parent: Person) {
          parent.children.add(this)
      }
  }
  ```

- クラスがプライマリコンストラクタを持つなら、それぞれのセカンダリコンストラクタはプライマリコンストラクタへ委譲する必要あり
  
  - 同クラスの他コンストラクタへの委譲は `this` キーワードを利用する
  
  ```kotlin
  class Person(val name: String) {
      constructor(name: String, parent: Person) : this(name) {
          parent.children.add(this)
      }
  }
  ```
  
  - 非抽象クラスがコンストラクタの宣言をしない場合、引数なしのプライマリコンストラクタが`public`スコープで生成される
    
    - 引数なしのコンストラクタが必要でない場合、`private constructor`で宣言する
  
  ```kotlin
  class DontCreateMe private constructor () {
  }
  ```

### インスタンスの生成

- Kotlinは`new`キーワードを持たない
  
  - コンストラクタの呼び出しは、関数の呼び出しと同様に行う
  
  ```kotlin
  val invoice = Invoice()
  
  val customer = Customer("Joe Smith")
  ```

### クラスメンバ

- クラス含めることができるメンバ
  - コンストラクタと初期化ブロック
  - [関数](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/functions.html)
  - [プロパティ](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/properties.html)
  - [ネストされたインナークラス](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/nested-classes.html)
  - [オブジェクトの宣言](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/object-declarations.html)

### 継承

- Kotlinの全てのクラスは共通の `Any` スーパークラスを持つ
  
  - `Any` は `java.lang.Object` ではない
    - 特に注意すべきは、 `equals()` 、 `hashCode()` 、 `toString()` 以外のメンバを持たない
      - 詳細については [Javaとの相互運用性](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/java-interop.html#object-methods) を参照
  
  ```kotlin
  class Example // Anyから暗黙の継承
  ```

- クラスヘッダ内のコロンの後に型を書くと、明示的にスーパータイプを宣言できる
  
  - スーパータイプのクラスがプライマリコンストラクタを持つなら、継承したクラスのプライマリコンストラクタの値を利用して、初期化しなければならない
  
  ```kotlin
  open class Base(p: Int)
  
  class Derived(p: Int) : Base(p)
  ```
  
  - スーパータイプがプライマリコンストラクタを持たないならば、セカンダリコンストラクタで`super`キーワードを利用して初期化する
  
  ```kotlin
  class MyView : View {
      constructor(ctx: Context) : super(ctx) {
      }
  
      constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) {
      }
  }
  ```

- クラスの `open` アノテーションは、Javaの `final` と反対
  
  - デフォルトでは、Kotlinのすべてのクラスは [Effective Java](http://www.oracle.com/technetwork/java/effectivejava-136174.html) のアイテム17（ *継承またはそれの禁止のためのデザインとドキュメント* ）に合致する `final`となる

#### オーバーライド

- Kotlinは明示的であり、Javaとは異なりオーバーライドできるメンバには`open`キーワードを付与する
  
  - サブクラスでは、`override`キーワードを利用して、スーパークラスの関数をオーバーライドする
  - `open`キーワードのないクラスでは、`open`なメンバは禁止されている
  
  ```kotlin
  open class Base {
    open fun v() {} // オーバーライド可能
    fun nv() {}　// オーバーライド不可
  }
  
  class Derived() : Base() {
    override fun v() {} // Base .v() をオーバーライド、 open を引き継ぐ
  }
  
  open class AnotherDerived() : Base() {
    final override fun v() {}　// Base .v() をオーバーライド、 これ以上のオーバーライドは不可
  }
  ```

- プロパティのオーバライドもメソッドのオーバライドと同様
  
  ```kotlin
  open class Foo {
      open val x: Int get { ... }
  }
  
  class Bar1(override val x: Int) : Foo() {
  }
  ```

### 抽象クラス

- クラスとそのメンバは `abstract`キーワードを使用して抽象クラス・抽象メンバとして宣言できる
  
  - 抽象クラスや抽象関数に`open`キーワードを付ける必要はない
  
  ```kotlin
  open class Base {
    open fun f() {}
  }
  
  abstract class Derived : Base() {
    override abstract fun f()
  }
  ```

### コンパニオンオブジェクト

- Kotlinでは、JavaやC＃とは異なり、クラスは`static`メソッドを持たない
  - ほとんどの場合、代替として、パッケージレベルの関数を使用することが推奨されている
  - もしクラスインスタンスを持たずに呼べるがクラス内部（例えばファクトリメソッド）へのアクセスが要る関数を書く必要があれば、そのクラスの中で [オブジェクト宣言](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/object-declaration.html) のメンバとして書くことができる

## プロパティとフィールド

### プロパティの宣言

- Kotlinのクラスは、プロパティを持てる
  
  - `var` キーワード: ミュータブル（可変）
  - `val` キーワード: イミュータブル（読み取り専用）
  
  ```kotlin
  public class Address { 
    public var name: String = ...
    public var street: String = ...
    public var city: String = ...
    public var state: String? = ...
    public var zip: String = ...
  }
  ```

- プロパティの参照
  
  - Javaのフィールド参照と同様
  
  ```kotlin
  fun copyAddress(address: Address): Address {
    val result = Address() // 'new' キーワードは Kotlin にありません
    result.name = address.name // アクセサが呼ばれる
    result.street = address.street
    // ...
    return result
  }
  ```

### ゲッターとセッター

- プロパティを宣言するための構文
  
  - イニシャライザ、ゲッターとセッターは必須ではない
  
  ```kotlin
  // ミュータブル (var) の場合
  var allByDefault: Int? // エラー：明示的なイニシャライザが必要、デフォルトのゲッターとセッターは暗黙
  var initialized = 1 // これは Int 型を持ち、ゲッターとセッターも持つ
  
  // イミュータブル (val) の場合 : setter が生成されない
  val simple: Int? // Int 型を持ち、デフォルトゲッターを持つ。コンストラクタ内で初期化が必要
  val inferredType = 1 // Int 型を持ち、デフォルトゲッターを持つ
  ```

- カスタムアクセサの定義
  
  ```kotlin
  // カスタム getter
  val isEmpty: Boolean
    get() = this.size == 0
  
  // カスタム setter
  var stringRepresentation: String
    get() = this.toString()
    set(value) {
      setDataFromString(value) // 文字列をパースして他のプロパティへ値を代入する
    }
  ```

- アクセサの可視性を変更したり、アノテーションを付ける必要があるが、デフォルトの実装を変更する必要がない場合
  
  - 本体を定義せずにアクセサを定義することがでる
  
  ```kotlin
  var setterVisibility: String = "abc"
    private set // セッターはプライベートでデフォルトの実装を持つ
  
  var setterWithAnnotation: Any? = null
    @Inject set // セッターに Inject でアノテーションを付ける
  ```

### バッキングフィールド (Backing Fields)

- Kotlinのクラスは、フィールドを持てない
  
  - カスタムアクセサを使用するときにバッキングフィールドが必要になることがある
    - この目的のために、Kotlinは自動バッキングフィールドを提供する
      - `field` 識別子を使用してアクセスすることができる
  
  ```kotlin
  var counter = 0 // イニシャライザの value はバッキングフィールドへ直に書き込まれる
    set(value) {
      if (value >= 0)
        field = value // バッキングフィールドへ値を設定する
    }
  ```

### コンパイル時定数

- 値がコンパイル時にわかるプロパティは、 `const` キーワードを使用して、 *コンパイル時定数 (compile time constants)* としてマークすることができる
  
  - 次の要件を満たす場合に利用できる
    - トップレベルまたは `object` のメンバ
    - `String`型の値またはプリミティブ型で初期化される
    - カスタムゲッターが無い
  
  ```kotlin
  const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
  
  @Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }
  ```

### 遅延初期化プロパティ

- 通常、非null型として宣言されたプロパティは、コンストラクタ内で初期化が必要
  
  - `lateinit` 修飾子でプロパティをマークすることで、コンストラクタで初期化ができないケースをカバー
    - カスタムゲッターやカスタムセッターを持たない `var` プロパティでのみ使用でき、プロパティの型が非nullかつ、プリミティブ型であってはならない
    - `lateinit` プロパティが初期化される前にアクセスした場合、アクセスされたプロパティと、それが初期化されていないことを特定するための例外がスローされる
  
  ```kotlin
  public class MyTest {
      lateinit var subject: TestSubject
  
      @SetUp fun setup() {
          subject = TestSubject()
      }
  
      @Test fun test() {
          subject.method()  // 参照先を直に見に行く(dereference directly)
      }
  }
  ```

## 継承

### インターフェース

- `interface` キーワードを使用して定義
  
  ```kotlin
  interface MyInterface {
      fun bar()
      fun foo() {
        // 本体は任意
      }
  }
  ```

### インタフェースの実装

- クラスやオブジェクトは、複数のインターフェイスを実装すできる
  
  ```kotlin
  class Child : MyInterface {
     override fun bar() {
        // 本体
     }
  }
  ```

### インターフェイス内のプロパティ

- プロパティの宣言が可能
  
  ```kotlin
  interface MyInterface {
      val property: Int // abstract
  
      val propertyWithImplementation: String
          get() = "foo"
  
      fun foo() {
          print(property)
      }
  }
  
  class Child : MyInterface {
      override val property: Int = 29
  }
  ```

### オーバーライドの競合解決

```kotlin
interface A {
  fun foo() { print("A") }
  fun bar()
}

interface B {
  fun foo() { print("B") }
  fun bar() { print("bar") }
}

class C : A {
  override fun bar() { print("bar") }
}

class D : A, B {
  override fun foo() {
    super<A>.foo()
    super<B>.foo()
  }
}
```

## 可視性修飾子

- 4つの可視性修飾子 *(visibility modifiers)*
  - `private`
  - `protected`
  - `internal`
  - `public` : デフォルト

### パッケージ

- 関数、プロパティやクラス、オブジェクトやインターフェースは、「トップレベル」、つまり、パッケージ内部で直接宣言することができる
  
  - 可視性修飾子を何も指定しない: どこからでも参照可、デフォルト `public`
  - `private` : その宣言を含むファイルの中でのみ参照可
  - `internal` : 同一モジュール内から参照可
  - `protected` : トップレベルの宣言では使用不可
  
  ```kotlin
  // ファイル名: example.kt
  package foo
  
  private fun foo() {} // example.kt の中で見える
  
  public var bar: Int = 5 // プロパティはどこでも見える
      private set         // セッターは example.kt の中でのみ見える
  
  internal val baz = 6    // 同じモジュール内でのみ見える
  ```

### クラスとインタフェース

- クラス内のメンバーで指定した場合
  
  - `private` : そのクラス内のみ参照可
    - *注意* Javaのユーザーへ：Kotlinでは、外部クラスはその内部クラスの`private` メンバを参照不可
  - `protected` :  `private` と同じ + サブクラス内のみ参照可
    - *注意* Javaのユーザーへ：Javaでは同一パッケージ内からでも`protected` のメンバ参照できるが、Kotlinでは不可
  - `internal` : 同一モジュール内から参照可
  - `public` – どこからでも参照可
  
  ```kotlin
  open class Outer {
      private val a = 1
      protected open val b = 2
      internal val c = 3
      val d = 4  // デフォルトで public
  
      protected class Nested {
          public val e: Int = 5
      }
  }
  
  class Subclass : Outer() {
      // a は見えない
      // b, c, d は見える
      // Nested と e は見える
  
      override val b = 5   // 'b' は protected
  }
  
  class Unrelated(o: Outer) {
      // o.a, o.b は見えない
      // o.c and o.d は見える（同じモジュール）
      // Outer.Nested, Nested::e は見えない
  }
  ```

### モジュール

- モジュールとは
  - Kotlin のファイルが一体としてコンパイルされるまとまりのこと
    - 例
      - IntelliJ IDEAモジュール
      - MavenやGradleのプロジェクト
- Javaでは、外部のコードが同じパッケージ名でクラスを定義すれば元のコードのパッケージプライベートな宣言を参照できるが、kotlinでは不可
  - 実装のカプセル化を防ぐための機能

## 拡張 (extension)

- クラスを新しい機能で拡張する機能
  - *拡張関数* と *拡張プロパティ* をサポート

### 拡張関数

- 拡張関数を宣言するには *レシーバタイプ (receiver type)* を関数名の前に付ける
  
  - 拡張関数内での `this` キーワードは、レシーバオブジェクト（ドットの前に渡されたもの）に対応する
  
  ```kotlin
  // MutableListにswap 関数を追加する例
  fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1] // 'this' はリストに対応する
    this[index1] = this[index2]
    this[index2] = tmp
  }
  ```

#### null許容レシーバー

- 拡張はnull許容なレシーバの型でも定義できる
  
  - 対象の値が`null`の場合でも、オブジェクト変数で呼び出すことができ、かつその本体内で `this == null` をチェックすることが可能
  
  ```kotlin
  fun Any?.toString(): String {
      if (this == null) return "null"
      // nullチェックの後だと、 'this' は非null型に自動キャストされるので、
      // 下記の toString() は Any クラスのメンバであると解決される
      return toString()
  }
  ```

## データクラス

- データを保持するためだけのクラス (DTO, VO)

  - プライマリコンストラクタで宣言されたすべてのプロパティから、コンパイラは自動的に次のメンバを推論
    - `equals()` / `hashCode()` のペア
    - `"User(name=John, age=42)"` 形式の `toString()` 
    - 宣言した順番でプロパティに対応する [`componentN()` 関数](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/multi-declarations.html)
    - `copy()` 関数
  - 制約
    - プライマリコンストラクタは、少なくとも1つのパラメータを持ち、 `val` または `var` としてマークする
    - データクラスは、`abstract`, `open`, `sealed` `inner` にできない

  ```kotlin
  data class User(val name: String, val age: Int)
  
  // デフォルト値を指定することで、パラメータなしのコンストラクタを定義できる
  data class User(val name: String = "", val age: Int = 0)
  ```

### コピー

- 自動的に生成される`copy()`関数は、対象のオブジェクトのクローンを生成する

  ```kotlin
  val jack = User(name = "Jack", age = 1)
  val olderJack = jack.copy(age = 2)
  ```

### データクラスと分解宣言 (Destructuring Declarations)

- [分解宣言](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/multi-declarations.html)で特定のプロパティ値を変数に展開ができる

  ```kotlin
  val jane = User("Jane", 35) 
  val (name, age) = jane // Destructuring
  println("$name, $age years of age") // "Jane, 35 years of age" を出力する
  ```

### 標準データクラス

- 標準ライブラリは、 `Pair` と `Triple` を提供（tupleに相当）

## ジェネリクス

- Javaと同様に、型パラメータを持てる

  ```kotlin
  class Box<T>(t: T) {
    var value = t
  }
  
  // インスタンスを生成する
  val box: Box<Int> = Box<Int>(1)
  
  // 推論により型引数を省略できる
  val box = Box(1)
  ```

### 分散

- Javaのジェネリクスにあるワイルドカード（[JavaのジェネリックのFAQ](http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html)を参照）がない
  - Javaでのワイルドカード例: `Collection<? extends Object>` , `List<? super String>`
    - `extends` : **型共変** - *Producer*で利用する -> Kotlin `out`修飾子
    - `super` : **反変性** - *Consumer*で利用する -> Kotlin `in`修飾子
- Tips : [Wikipedia 共変性と反変性 (計算機科学)](https://ja.wikipedia.org/?curid=1781428)より
  - **共変 (covariant):** 広い型（例：`double`）から狭い型（例：`float`）へ変換すること
  - **反変 (contravariant) :** 狭い型（例：`float`）から広い型（例：`double`）へ変換すること
  - **不変 (invariant):** 型を変換できないこと


#### 宣言箇所分散

##### 分散アノテーション

- `out` / `in `修飾子をしない型パラメータは**不変**となる

  ```kotlin
  open class Present(private val price: Int)
  class Sweets(price: Int, private val flavor: String) : Present(price)
  class HandCream(price: Int) : Present(price)
  
  // T はへ不変
  class Box<T : Present>(private val contents: T) {
      fun take(): T = contents
      fun <R> take(predicate: (T) -> R): R = predicate(contents)
  }
  
  fun main() {
      var candidate1: Box<Present> = Box(Present(3000))
      var candidate2: Box<Sweets> = Box(Sweets(2000, "ビターチョコ"))
  
      candidate1 = candidate2 // コンパイルエラー : Type mismatch
  }
  
  ```

###### `out` 修飾子

- 「読み取りはするが、変更はしない」状態にすることで、広い型から狭い型への変換が可能

  ```kotlin
  // T は out 修飾子により共変
  class Box<out T : Present>(private val contents: T) {
      fun take(): T = contents
      fun <R> take(predicate: (T) -> R): R = predicate(contents)
  }
  
  fun main() {
      var candidate1: Box<Present> = Box(Present(3000))
      var candidate2: Box<Sweets> = Box(Sweets(2000, "ビターチョコ"))
  
      candidate1 = candidate2 // OK
  }
  ```

- 例) Kotlinの `List` は __immutable__ であるため、 `out`修飾子が利用されている

  ```kotlin
  public interface List<out E> : Collection<E>
  ```

###### `in` 修飾子

- 「変更はするが、読み取りはしない」状態にすることで、狭い型から広い型への変換が可能

  ```kotlin
  // T は in 修飾子により反変
  class Box<in T : Present>(private var contents: T) {
      //他のTを引数に取り、プロパティのTを書き換える「だけの」メソッド (内部のT(contentsプロパティ)を参照してはいけない)
      fun changeContents(other: T) {
          contents = other
      }
  
      // 値を参照するような処理はできない
      //fun <R> take(predicate: (T) -> R): R = predicate(contents)
  }
  
  fun main() {
      val candidate1 = Box(Present(3000))
      var candidate2 = Box(Sweets(2000, "ビターチョコ"))
  
      // 広い型を狭い型へ代入する = 狭い型を広い型に変換することが可能
      candidate2 = candidate1
  
      candidate2.changeContents(Sweets(5000, "抹茶チョコ"))
  }
  ```

##### タイププロジェクション（型投影）

- 例として、配列を表す `Array` は読み書きができるため __不変__ となる

  ```kotlin
  // ある配列から別の配列へ、アイテムをコピーする関数
  fun copy(from: Array<Any>, to: Array<Any>) {
    assert(from.size == to.size)
    for (i in from.indices)
    to[i] = from[i]
  }
  
  val ints: Array<Int> = arrayOf(1, 2, 3)
  val any = Array<Any>(3) {}
  copy(ints, any) // エラー： (Array<Any>, Array<Any>) が期待されている
  ```

- `out` 修飾子を利用して、`copy ` 関数が  `from` に変更を禁止することを保証する

  - Javaの `Array<? extends Object>` に対応

  ```kotlin
  fun copy(from: Array<out Any>, to: Array<Any>) {
  ...
  }
  
  val ints: Array<Int> = arrayOf(1, 2, 3)
  val any = Array<Any>(3) {}
  copy(ints, any) // OK
  ```

- `in`修飾子を利用して、与えられたパラメータの読み込みを禁止することを保証する

  - Javaの `Array<? super String>` に対応

  ```kotlin
  // dest の型パラメータに in を指定してるため dest は 引数に型パラメータを使うメソッドしか使えない
  fun fill(dest: Array<in String>, value: String) {
    // ...
  }
  ```

##### スタープロジェクション (star-projections)

- Java において  `Some<?>` の様に、型パラメータを指定しない場合、Kotlinでは `Some<*>`  と記述し、スタープロジェクションと呼ばれる。

  - `Some<out Any?>`と同じ意味を持つ

  ```kotlin
  val ints: List<Int> = listOf(1, 2, 3)
  val otherInts: List<*> = ints // スタープロジェクション
  
  // otherIntList は何の型を内部に格納しているか不明なので、 Any? としてしか取り出せない
  val a: Any? = otherInts[0] // OK
  val n: Number = otherInts[0] // エラー
  val i: Int = otherInts[0]) // エラー
  ```

## ネストクラス

### クラスのネスト

- クラス内にクラスを定義できる

  ```kotlin
  class Outer {
    private val bar: Int = 1
    class Nested {
      fun foo() = 2
    }
  }
  
  val demo = Outer.Nested().foo() // == 2
  ```

### 内部クラス

- `inner`を付与することで、外部クラスのメンバーを参照できる

  - 内部クラスで`this`を利用する場合の曖昧さに注意 : [修飾された *this* 式](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/this-expressions.html)

  ```kotlin
  class Outer {
    private val bar: Int = 1
    inner class Inner {
      fun foo() = bar
    }
  }
  
  val demo = Outer().Inner().foo() // == 1
  ```

### 無名内部クラス

- [オブジェクト式](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/object-declarations.html#object-expressions)を利用して、無名内部クラスのインスタンスを生成する

  ```kotlin
  window.addMouseListener(object: MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
      // ...
    }
                                                        
    override fun mouseEntered(e: MouseEvent) {
      // ...
    }
  })
  ```

- 生成するオブジェクトがFunction Interface（インターフェースに抽象メソッドが1つだけ宣言されている）場合は、ラムダ式を使用してオブジェクトを作成できる

  ```kotlin
  val listener = ActionListener { println("clicked") }
  ```

## 列挙型クラス (Enum Classes)

- 基本的な列挙型の例

  ```kotlin
  enum class Direction {
    NORTH, SOUTH, WEST, EAST
  }
  ```

### メンバの初期化

- メンバを持つ列挙型の例

  ```kotlin
  enum class Color(val rgb: Int) {
      RED(0xFF0000),
      GREEN(0x00FF00),
      BLUE(0x0000FF)
  }
  ```

### 無名クラス

- 独自の無名クラスを宣言する例

  ```kotlin
  enum class ProtocolState {
    WAITING {
      override fun signal() = TALKING
    },
  
    TALKING {
      override fun signal() = WAITING
    };
  
    abstract fun signal(): ProtocolState
  }
  ```

### 列挙型に用意されたメソッド・プロパティ

- Javaの`enum`と同様のメソッド・プロパティが提供される

  ```kotlin
  // emum class EnumClass を定義した場合の例
  
  // 指定された名前が、クラスで定義されている列挙型定数のいずれとも一致しない場合、valueOf() メソッドは IllegalArgumentException をスロー
  EnumClass.valueOf(value: String): EnumClass
  EnumClass.values(): Array<EnumClass>
  ```

- Javaと同様に、すべての列挙型定数は、列挙型クラス宣言でその名前と順序を取得するためのプロパティが提供される

  - 定義された順に基づいた[Comparable](https://dogwood008.github.io/kotlin-web-site-ja/api/latest/jvm/stdlib/kotlin/-comparable/index.html) インタフェースも提供される

  ```kotlin
  val name: String
  val ordinal: Int
  ```

## オブジェクト

### オブジェクト宣言

- Kotlinにおけるオブジェクトは[シングルトン](http://en.wikipedia.org/wiki/Singleton_pattern)である

  - 初回アクセス時に **遅延して** 初期化される

  ```kotlin
  // オブジェクトの宣言
  object DataProviderManager {
    fun registerDataProvider(provider: DataProvider) {
      // ...
    }
  
    val allDataProviders: Collection<DataProvider>
      get() = // ...
  }
  
  // オブジェクトの参照
  DataProviderManager.registerDataProvider(...)
  
  // スーパータイプを持つ宣言の例
  object DefaultListener : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
      // ...
    }
  
    override fun mouseEntered(e: MouseEvent) {
      // ...
    }
  }
  ```

#### コンパニオンオブジェクト (Companion Objects)

- クラス内におけるオブジェクトの宣言は`companion`キーワードを使用する 

  - Javaにおける`static`に相当する利用方法となる
  - 対応するクラスが読み込まれたときに初期化される

  ```kotlin
  class MyClass {
    companion object Factory {
      fun create(): MyClass = MyClass()
    }
  }
  
  // コンパニオンオブジェクトのメンバーを呼び出す例
  val instance = MyClass.create()
  ```

### オブジェクト式

- あるクラスをわずかに修正しただけのオブジェクトを、それのための新しいサブクラスを明示的に宣言せずに、作成する必要がある時、Javaでは *無名内部クラス* で対応する

  -  Kotlinでは`object`キーワードを利用した無名クラスのオブジェクトの生成で対応する

  ```kotlin
  // MouseAdapterのオブジェクトを生成する例
  window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) {
      // ...
    }
  
    override fun mouseEntered(e: MouseEvent) {
      // ...
    }
  })
  
  // 複数のスーパータイプを持つ例
  open class A(x: Int) {
    public open val y: Int = x
  }
  
  interface B {...}
  
  val ab: A = object : A(1), B {
    override val y = 15
  }
  
  // 一時的なオブジェクトのみが必要な場合の例
  val adHoc = object {
    var x: Int = 0
    var y: Int = 0
  }
  print(adHoc.x + adHoc.y)
  ```

## 委譲 (Delegation)

### クラスの委譲

- 実装継承はカプセル化を破るため[Delegationパターン](https://en.wikipedia.org/wiki/Delegation_pattern)が代替として推奨される（もちろんケースバイケースではある）

  ```kotlin
  interface Base {
    fun print()
  }
  
  class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
  }
  
  // スーパータイプのリスト中の by 節は、 b が Derived のオブジェクトに内部的に格納されることを示し、コンパイラは b に取り次ぐ Base のすべてのメソッドを生成
  class Derived(b: Base) : Base by b
  
  fun main(args: Array<String>) {
    val b = BaseImpl(10)
    Derived(b).print() // 出力：10
  }
  ```

### 委譲プロパティ (Delegated Properties)

- 委譲を行うことで、次の一般的なユースケースに対応できる

  - 遅延プロパティ (lazy properties) ：アクセス時に算出する
  - オブザーバブルプロパティ (observable properties) ：プロパティが変更された時に通知する

  ```kotlin
  class Example {
    var p: String by Delegate()
  }
  
  class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
      return "$thisRef, thank you for delegating '${property.name}' to me!"
    }
   
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
      println("$value has been assigned to '${property.name} in $thisRef.'")
    }
  }
  
  val e = Example()
  println(e.p) // -> Example@33a17727, thank you for delegating ‘p’ to me!
  ```

# 関数とラムダ

## 関数

### 関数の宣言と呼び出し

- `fun`キーワードで宣言する

  ```kotlin
  // 宣言
  fun double(x: Int): Int {
  }
  
  // 呼び出し
  val result = double(2)
  ```

#### 中置記法

- `infix`キーワードを付与することで中置記法で関数を実行できる

  - 中置記法が使えるケース
    - メンバ関数や[拡張関数](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/extensions.html)
    - 単一のパラメータ

  ```kotlin
  // Intにエクステンションを定義
  infix fun Int.shl(x: Int): Int {
  ...
  }
  
  // 中置記法で実行
  1 shl 2
  
  // これは次と同じ
  1.shl(2)
  ```


#### 引数のデフォルト値

- 関数パラメータは、対応する引数が省略されている際に使用されるデフォルト値を持てる

  ```kotlin
  fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size()) {
  ...
  }
  ```

#### 名前付きパラメータ

- 関数の呼び出し時に、関数のパラメータに名前を付けて呼ぶことができる

  - Javaバイトコードは関数パラメータの名を保存しないため、Java関数を呼び出すときに名前付きパラメータ構文は使用できない

  ```kotlin
  fun reformat(str: String,
               normalizeCase: Boolean = true,
               upperCaseFirstLetter: Boolean = true,
               divideByCamelHumps: Boolean = false,
               wordSeparator: Char = ' ') {
  ...
  }
  
  // デフォルト引数を利用して関数を呼び出す
  reformat(str)
  
  // 全ての引数を指定して関数を呼び出す
  reformat(str, true, true, false, '_')
  
  // 名前付き引数で関数を呼び出す
  reformat(str,
      normalizeCase = true,
      upperCaseFirstLetter = true,
      divideByCamelHumps = false,
      wordSeparator = '_'
    )
  
  // 名前付き引数を利用して一部の引数を指定して呼び出す
  reformat(str, wordSeparator = '_')
  ```

####  Unit

- 関数が任意の有用な値を返さない場合、その戻り値の型は `Unit`となる（Javaの`void/Void`に相当）

  ```kotlin
  fun printHello(name: String?): Unit {
      if (name != null)
          println("Hello ${name}")
      else
          println("Hi there!")
      // `return Unit` または `return` は必須ではない
  }
  
  // Unitは省略できる（上記の関数宣言と同一となる）
  fun printHello(name: String?) {
      ...
  }
  ```

#### 単一式関数

- 関数の内部が単一の式である場合（つまり1行だけの場合）、中括弧を省略できる

  ```kotlin
  fun double(x: Int): Int = x * 2
  
  // コンパイラが型推論できる場合は、戻り値の型宣言を省略できる
  fun double(x: Int) = x * 2
  ```

#### 可変長パラメータ

- 関数のパラメータ（最後のひとつ）は、 `vararg` 修飾子で可変長パラメータにできる

  ```kotlin
  // ts 変数は Array<out T> 型
  fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts は配列
      result.add(t)
    return result
  }
  
  // 可変長パラメータを指定して関数を呼び出す
  val list = asList(1, 2, 3)
  ```

### スコープ

#### ローカル関数

- ある関数内に別の関数を定義できる

  - ローカル関数は、外側の関数（すなわちクロージャ）のローカル変数にアクセス可能

  ```kotlin
  fun dfs(graph: Graph) {
    val visited = HashSet<Vertex>()
  
    fun dfs(current: Vertex) {
      if (!visited.add(current)) return
      for (v in current.neighbors)
        dfs(v)
    }
  
    dfs(graph.vertices[0])
  }
  ```

#### メンバ関数

- クラスやオブジェクトの内部で定義される関数（いわゆるメソッド）

### ジェネリック関数

- 関数名の前に山括弧（<>のこと）を使用して、ジェネリックパラメータを持てる

  ```kotlin
  fun <T> singletonList(item: T): List<T> {
    // ...
  }
  ```

### 末尾再帰関数

- [末尾再帰](https://ja.wikipedia.org/wiki/%E6%9C%AB%E5%B0%BE%E5%86%8D%E5%B8%B0)と呼ばれる関数型プログラミングのスタイルをサポート、通常の再帰と異なりスタックオバーフローのリスクがない

- 関数が `tailrec` 修飾子でマークされており、必要な形式を満たしている場合、コンパイラは高速かつ効率的なループベースのバージョンコードを生成する

  - 必要な形式 : 関数は実行する最後の操作として自身を呼び出すこと

  ```kotlin
  // 末尾再帰の関数
  tailrec fun findFixPoint(x: Double = 1.0): Double
          = if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
  
  // 生成されるループベースのコード
  private fun findFixPoint(): Double {
      var x = 1.0
      while (true) {
          val y = Math.cos(x)
          if (x == y) return y
          x = y
      }
  }
  ```

## 高階関数とラムダ

### 高階関数

- [高階関数](https://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0)はパラメータとして関数を取るか、関数を返す関数のことを指す

### ラムダ

- 概要

  - ラムダ式は、中括弧で囲まれる
  - パラメータ（もしあれば）は、 `->` の前で宣言される（パラメータの型を省略可能）
  - 本体が `->` に続く（存在する場合）

  ```kotlin
  // body は関数型: () -> Tを持つ（パラメータを取らず、型 T の値を返す関数）
  fun <T> lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
      return body()
    }
    finally {
      lock.unlock()
    }
  }
  
  // lock関数を呼び出す例
  fun toBeSynchronized() = sharedResource.operation()
  val result = lock(lock, ::toBeSynchronized) // ::は関数の参照を示す
  
  // ラムダ式を利用してlock関数を呼び出す例
  val result = lock(lock, { sharedResource.operation() })
  
  // Kotlinでは、関数の最後のパラメータが関数である場合、そのパラメータは括弧の外に指定することができる
  val result = lock (lock) {
    sharedResource.operation()
  }
  ```

  ```kotlin
  val sum = { x: Int, y: Int -> x + y }
  
  // sum変数に明示的に型を記載した場合
  val sum: (Int, Int) -> Int = { x, y -> x + y }
  ```

#### `it` : 単一パラメータの暗黙の名前

- 関数リテラルがパラメータを1つだけ持つ場合、その宣言を（ `->` と一緒に）省略でき、暗黙のパラメータ名は `it` となる

  ```kotlin
  // 高階関数 map
  fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
    val result = arrayListOf<R>()
    for (item in this)
      result.add(transform(item))
    return result
  }
  
  // ラムダ式を利用して呼び出す
  ints.map({ it -> it * 2 })
  ints.map { it -> it * 2 }
  ints.map { it * 2 }
  ```

### 無名関数

- ラムダ式の構文から一つ欠落しているのは、関数の戻り値の型を指定する機能

  - ほとんどの場合は、戻り型を自動的に推論することができるので不要だが、明示的な型指定が必要な場合は無名関数を利用する

  ```kotlin
  fun(x: Int, y: Int): Int = x + y
  
  // ブロックを使用した場合
  fun(x: Int, y: Int): Int {
    return x + y
  }
  
  // 無名関数を別の関数のパラメータとして渡す
  ints.filter(fun(item) = item > 0)
  ```

#### ラムダ式と無名関数の違い

- ラベルなし`return`の動作が異なる

  | ラムダ式                              | 無名関数                                           |
  | ------------------------------------- | -------------------------------------------------- |
  | `return` は囲んでいる関数から返される | 無名関数の内部 `return` は無名関数自体から返される |

### クロージャ

- 外側のスコープで宣言された変数にアクセスすることができ、Javaとは異なりクロージャに取り込まれた変数を変更することができる（Javaでは`final`宣言をしなければならない）

  ```kotlin
  var sum = 0
  ints.filter { it > 0 }.forEach {
    sum += it
  }
  print(sum)
  ```

# 分解宣言 (Destructuring Declarations)

- オブジェクトの各プロパティが保持している値を、別々の変数に一度に代入することができる

  ```kotlin
  data class Person(
    var name: String,
    var age: Int
  )
  
  val p = Person(name = "yuki.terai", age = 17)
  val (name, age) = p
  // name=>"yuki.terai"
  
  
  // 宣言の順番通りに変数に入れていくだけなので、名前の一致はk関係ないため注意
  data class Person(
    var age: Int,
    var name: String
  )
  
  val p = Person(name = "yuki.terai", age = 17)
  val (name, age) = p
  // name=>17
  ```

# コレクション

- Kotlinは可変コレクションと不変コレクション（`List`、`Set`、`Map`など）を区別する

  - Kotlinの`List<out T>`は`size`や`get`などの参照のみ定義される
  - リストを変更するメソッドは、`MutableList<T>`インターフェースによって追加されている

  ```kotlin
  val numbers: MutableList<Int> = mutableListOf(1, 2, 3)
  val readOnlyView: List<Int> = numbers
  println(numbers)        // prints "[1, 2, 3]"
  numbers.add(4)
  println(readOnlyView)   // prints "[1, 2, 3, 4]"
  readOnlyView.clear()    // -> does not compile
  
  val strings = hashSetOf("a", "b", "c", "c")
  assert(strings.size == 3)
  ```

# 等価

- Kotlinには2つの等価性がある

  | 参照の等価性 (Javaの`==`)   | 構造的な等価性 (Javaの`equals`) |
  | --------------------------- | ------------------------------- |
  | `===` 演算子（および`!==`） | `==`演算子（および`!=`）        |

# `null`安全

## Nullable と Non-Null

- Kotlinでは、`null`を保持できる参照と、保持できない参照を区別する

  ```kotlin
  // Non-Null
  var a: String = "abc"
  a = null // compilation error
  a.length // ok
  
  // Nullable
  var b: String? = "abc"
  b = null // ok
  b.length // compilation error: variable 'b' can be null
  ```

### Nullableに対する参照方法

#### `null`をチェック

- Nullable な型に対し、`null`のチェックを行うことで、メンバへのアクセスが可能になる

  ```kotlin
  var b: String? = "abc"
  
  val l = if (b != null) b.length else -1　// ok
  
  if (b != null && b.length > 0)
    print("String of length ${b.length}") // このブロックは、null でないことが明白であることがコンパイラは知っている
  else
    print("Empty string")
  ```

#### `?.`演算子

- Nullable のオブジェクトのメンバにアクセスする際に`?.`を利用することで、安全に呼び出しが行える

  ```kotlin
  var b: String? = "abc"
  
  val l: Int? = b?.length // b が null の場合は l に null が入る
  
  // チェーンすることも可能
  bob?.department?.head?.name // いずれかのプロパティが null であれば null が返る
  ```

#### エルビス演算子

- `null` でない場合はその値を返し、そうでない場合は`null`以外の値を使用する

  ```kotlin
  // if 利用した場合
  val l: Int = if (b != null) b.length else -1
  
  // エルビス演算子を利用した場合
  val l = b?.length ?: -1
  ```

#### `!!.`演算子

- `null`の時に`NullPointerException`を発生させる（NPEの愛好家向け、利用はよく考えること）

  ```kotlin
  var b: String? = "abc"
  b = null
  val l = b!!.length() // NullPointerException が発生する
  ```

# アノテーション

## 宣言

- `class`の前に`annotation`を付与する

  - アノテーションの追加属性は、アノテーションクラスにメタアノテーションを付けることで指定できる
    - [`@Target`](https://dogwood008.github.io/kotlin-web-site-ja/api/latest/jvm/stdlib/kotlin.annotation/-target/index.html) : アノテーションを付けることができる要素（クラス、関数、プロパティ、式など）を指定する
    - [`@Retention`](https://dogwood008.github.io/kotlin-web-site-ja/api/latest/jvm/stdlib/kotlin.annotation/-retention/index.html) : アノテーションがコンパイルされたクラスファイルに保存されるかどうか、および実行時にリフレクションを通じて表示されるかどうかを指定する（デフォルトでは両方とも`true`）
    - [`@Repeatable`](https://dogwood008.github.io/kotlin-web-site-ja/api/latest/jvm/stdlib/kotlin.annotation/-repeatable/index.html) : 1つの要素に同じ注釈を複数回使用できる
    - [`@MustBeDocumented`](https://dogwood008.github.io/kotlin-web-site-ja/api/latest/jvm/stdlib/kotlin.annotation/-must-be-documented/index.html) : アノテーションがパブリックAPIの一部であり、生成されたAPIドキュメントに示されているクラスまたはメソッドのシグネチャに含まれている必要があることを指定する

  ```kotlin
  @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
          AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION)
  @Retention(AnnotationRetention.SOURCE)
  @MustBeDocumented
  public annotation class Fancy
  
  // アノテーションの使用例
  @Fancy class Foo {
    @Fancy fun baz(@Fancy foo: Int): Int {
      return (@Fancy 1)
    }
  }
  ```

### コンストラクタ

- アノテーションには、パラメーターを受け取るコンストラクターを指定できる

  - 許可されるパラメータタイプは次のとおりです。
    - Javaプリミティブ型（Int、Longなど）に対応する型
    - 文字列
    - クラス（`Foo::class`）;
    - `enum`型
    - その他のアノテーション
    - 上記のタイプの配列

  ```kotlin
  annotation class Special(val why: String)
  
  @Special("example") class Foo {}
  ```

## アノテーションを適用するJavaの要素

- プロパティまたはプライマリコンストラクタパラメータに注釈を付ける場合、Kotlinから生成されたJavaバイトコード内の注釈の可能な場所は複数になる。そのため、アノテーションを適用する箇所を指定することができる

  - `file`
  - `property` （このターゲットの注釈はJavaには表示されません）
  - `field`
  - `get` （プロパティゲッター）
  - `set` （プロパティセッター）
  - `receiver` （拡張関数またはプロパティのレシーバーパラメーター）
  - `param` （コンストラクターパラメーター）
  - `setparam` （プロパティセッターパラメーター）
  - `delegate` （委任されたプロパティの委任インスタンスを格納するフィールド）

  ```kotlin
  class Example(@field:Ann val foo,    // annotate Java field
                @get:Ann val bar,      // annotate Java getter
                @param:Ann val quux)   // annotate Java constructor parameter
  ```

# リフレクション

- `::`構文を利用する

  ```kotlin
  class MyClass
  
  // Class References
  val kClass: KClass<MyClass> = MyClass::class
  val javaClass: Class<MyClass> = MyClass::class.java
  
  // Function References
  fun isOdd(x: Int) = x % 2 != 0
  val refFun1: (Int) -> Boolean = ::isOdd
  val refFun2: Function1<Int, Boolean> = ::isOdd
  
  // Property References
  val str = "a"
  val refProperty: KProperty<Int> = str::length
  val refJavaGetter: Method? = str::length.javaGetter
  val refJavaField: Field? = str::length.javaField
  
  // Constructor References
  val refConstructor: Function<MyClass> = ::MyClass
  ```


# オペレータオーバーローディング

- KotlinにはJavaとは異なり、演算子の動作を変更することが可能
  - https://kotlinlang.org/docs/operator-overloading.html