【まとめ】Kotlin in Action を読んで「へぇ」ってなったこと

# はじめに
本記事は

https://book.mynavi.jp/ec/products/detail/id=78137

> 『[Kotlinイン・アクション](https://book.mynavi.jp/ec/products/detail/id=78137)』
> Dmitry Jemerov、Svetlana Isakova 著、長澤太郎、藤原聖、山本純平、yy_yank 訳

を読んで個人的に「へぇ」ってなったイディオム・設計思想・Tipsをまとめたものです。

<details><summary>私の前提知識</summary><div>

- *Oracle Certified Java Programmer, Gold SE 8* 保有
- Java 実務開発経験 3 カ月
- Kotlin 実務開発経験 5 カ月

</div></details>

# 第 1 章 Kotlin とは何か？ なぜ使うのか？
Kotlin は、静的型付け言語で、型推論をサポートしています。それによって、ソースコードを簡潔に保ちつつ、正確性とパフォーマンスを維持できます。

:grinning:「うん。」

# 第 2 章 Kotlin の基本
### カスタムアクセサ

```kotlin
class Rectangle(
    val height: Int,
    val width: Int
) {
    val isSquare: Boolean
    	get() = height == width
}
```

*isSquare* プロパティは、値をフィールドに格納する必要はありません。ここにはカスタム getter の実装があるだけです。必要な値は、プロパティから値を取得するたびに毎回計算されます。

https://pl.kotl.in/_Px44R49O

:thinking: 「うん。でもこの例の場合、*getter* の意味ある？イミュータブルだから初期代入でよいのでは。」

# 第 3 章 関数の定義と呼び出し
### ペアを扱う
マップを生成するためには、*mapOf* 関数を使用します。

```kotlin
val map = mapOf(1 to "one", 7 to "seven", 53 to "fifty-three")
```

このコードの *to* という言葉は、組み込みの機能ではなく、特別な種類のメソッド呼び出しであり、**中置呼び出し**（infix call）と呼ばれています。次の 2 つの呼び出しは等価です。

```kotlin
1.to("one")
1 to "one"
```

中置呼び出しは、1 つの必須な引数を持った通常のメソッドや拡張関数で使用可能です。中置記法を使って関数を呼び出すためには、その関数に *infix* 修飾子を付ける必要があります。

```kotlin
infix fun Any.to(other: Any) = Pair(this, other)
```

*to* 関数は、*Pair* のインスタンスを返します。

```kotlin
val (number, name) = 1 to "one"
```

この機能を**分解宣言**（destructuring declaration）と呼びます。

:smile:「へぇ。」

# 第 4 章 クラス、オブジェクト、インタフェース
### open、final、abstract 修飾子
ご存じの通り、Java では、明示的に *final* キーワードを付けない限り、どのようなクラスのサブクラスでも作成可能で、すべてのメソッドをオーバーライドできます。これは便利ですが、いわゆる**壊れやすい基底クラス**（fragile base class）と呼ばれる問題を引き起こすこともあります。基底クラスのコードが変更されたときに、その変更がサブクラスが期待するものではなくなってしまったために、サブクラスでの不正な挙動を引き起こすということです。
Java プログラミングスタイルの名著である『[Effective Java](https://www.maruzen-publishing.co.jp/item/b303408.html)』Joshua Bloach 著、柴田　芳樹 訳 では、「継承のために設計および文書化する。でなければ継承を禁止する」と勤めています。つまり、サブクラスによってオーバーライドされることを特別に意図していないすべてのクラスやメソッドは、明示的に *final* と指定すべきであるということを意味しています。

Kotlin は、この思想を受け継いでいます。したがって、Kotlin の場合はデフォルトで *final* です。

| 修飾子 | 対応するメンバ | コメント |
| --- | --- | --- |
| *final* | オーバーライドできない | クラスメンバのデフォルト値として指定されている |
| *open* | オーバーライドできる | 明示的に指定する必要がある |
| *abstract* | オーバーライドしなければいけない | 抽象クラスのみで使用可能。抽象メンバは実装を持つことができない |
| *override* | スーパークラスかインタフェースのメンバをオーバーライドする | *final* と指定されていない場合、オーバーライドされるメンバはデフォルトで *open* |

:grinning:「うんうん。」

### 可視性修飾子
Java のデフォルトの可視性であるパッケージジプライベートは Kotlin には存在しません。Kotlin におけるパッケージは、名前空間にコードをまとめるためだけに使用され、可視性の制御には使用されません。
それとは別に、Kotlin では *internal* という新しい修飾子を提供しています。これは「モジュール内で参照可能」という意味です。

| 修飾子 | クラスメンバ | トップレベルの宣言 |
| --- | --- | --- |
| *public*（デフォルト） | どこからも参照可能 | どこからも参照可能 |
| *internal* | モジュール内からのみ参照可能 | モジュール内からのみ参照可能 |
| *protected* | サブクラスから参照可能 | |
| *private* | クラス内からのみ参照可能 | ファイル内からのみ参照可能 |

internal 修飾子はバイトコード上では public になります。

:grinning:「うんうん。」

### シールドクラス
スーパークラスに *sealed* 修飾子を設定すると、生成可能なサブクラスを制限できます。すべての直接のサブクラスは、スーパークラスにネストされている必要があります。

```kotlin
sealed class Expr { // 取りうるサブクラスをすべてネストされたクラスとして列挙
    class Num(val value: Int) : Expr()
    class Sum(val left: Expr, val right: Expr): Expr()
}

fun eval(e: Expr): Int =
    when (e) { // sealed により when 式はとりうるすべてのケースをカバーするので else 分岐は必要ない
        is Expr.Num -> e.value
        is Expr.Sum -> eval(e.left) + eval(e.right)
    }
```

https://pl.kotl.in/cfAtsc8uK

*when* 式内のすべてのシールドクラスのサブクラスを処理するのであれば、デフォルトの分岐 *else* を追加する必要はありません。
*when* を *sealed* クラスと一緒に使っており、新しいサブクラスを追加する際、値を返す *when* 式はコンパイルに失敗します。コードを変更しなければいけないと指摘しているのです。

https://kotlinlang.org/docs/sealed-classes.html

:open_mouth:「へぇ。安全だし便利。」

### クラスを初期化する

```kotlin
class User(val nickname: String)
```

このように丸括弧で囲まれたコードブロックは、**プライマリコンストラクタ**と呼ばれます。これは、コンストラクタの引数を指定し、それらの引数で初期化されるプロパティを定義するという 2 つの役割を担っています。

```kotlin
class User constructor(_nickname: String) {
    val nickname: String

    init {
        nickname = _nickname
    }
```

*constructor* キーワードは、プライマリもしくはセカンダリコンストラクタの宣言のはじめに付けられます。
*init* キーワードは、**初期化ブロック**（initializer block）を実装するためのキーワードです。このブロックは、クラスが生成されたときに実行される初期化コードを含み、プライマリコンストラクタと一緒に使用されることが意図されています。なぜなら、プライマリコンストラクタの構文には制約があり、初期化コードを含むことができないからです。

:grinning:「へぇ。自由度高い。」

### *getter* と *setter* からバッキングフィールドにアクセスする
値を格納するプロパティと、その値を取得または変更したときに実行される追加のロジックを実装する方法を見てみましょう。これをサポートするために、アクセサからプロパティのバッキングフィールドにアクセスできる必要があります。

```kotlin
class User(val name: String) {
    var address: String = "unspecfied"
    	set(value: String) {
        	println("""
         		Address was changed for $name:
         		"$field" -> "$value".
            """.trimIndent())
         	field = value // address に代入すると再度セッターが呼ばれオーバーフローする
        }
}
```

https://pl.kotl.in/LMGZv25Ex

*setter* の本体では、*field* という特別な識別子を使って、バッキングフィールドの値にアクセスします。
バッキングフィールドを持つプロパティと、持たないプロパティの間にはどのような違いがあるのか、不思議に思うかもしれません。バッキングフィールドへの明示的な参照がある場合とデフォルトのアクセサの実装を使用する場合に、コンパイラはプロパティのバッキングフィールドを生成します。カスタムアクセサの実装が *field* を使わない場合、バッキングフィールドは存在しません。

:grinning:「へぇ。試しにバッキングフィールド使わなかったら *StackOverflow* したよね。(そりゃそう)」

### アクセサの可視性を変更する
アクセサの可視性は、デフォルトではプロパティと同じです。しかし、*get* もしくは *set* キーワードの前に可視性修飾子を置くことで、必要に応じて可視性を変更できます。

```kotlin
class LengthCounter {
    var counter: Int = 0
    	private set
    
    fun addWord(word: String) {
        counter = word.length
    }
}
```

https://pl.kotl.in/kEl3KNJxX

:grinning:「へぇ。でもこれ忘れちゃいそう。」

### クラス委譲
Kotlin では、委譲パターンが第一級言語機能としてサポートされています。インタフェースを実装しているなら、*by* キーワードを使うことによって、いつでもインタフェースの実装を別のオブジェクトに**委譲**（delegate）できます。

```kotlin
class DelegatingCollection<T> : Collection<T> {
	private val innerList = arrayListOf<T>()
    
    override val size: Int get() = innerList.size
    override fun isEmpty(): Boolean = innerList.isEmpty()
    override fun contains(element: T): Boolean innerList.contains(element)
    override fun iterator(): Iterator<T> = innerList.iterator()
    override fun containsAll(elements: Collection<T>): Boolean =
    	innerList.containsAll(elements)
}
```

↓

```kotlin
class DelegatingCollection<T>(
	innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {}
```

クラス内のすべてのメソッド実装がどこかに行ってしまいました。その部分はコンパイラが生成しますが、実装は 1 つ目と似たものになります。
いくつかのメソッドの振る舞いを変更する必要があるときは、そのメソッドをオーバーライドできます。

```kotlin
class DelegatingCollection<T>(
	innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {
    var objectAdded = 0
    
    override fun add(element: T): Boolean {
        objectAdded++
        return innerList.add(element)
    }
    override fun addAll(c: Collection<T>): Boolean {
        objectAdded += c.size
        return innerSet.addAll(c)
    }
}
```

:dizzy_face:「へぇ。これが *Delegate Pattern* ってやつか。」

### コンパニオンオブジェクト
トップレベル関数はクラスの *private* メンバにアクセスすることができません。
したがって、クラスのインスタンスを持たずに呼び出しが可能で、クラスの内部にアクセスする必要がある関数を書く場合、そのクラスの内部のオブジェクト宣言のメンバとして関数を書くことができます。そのような関数の例は、ファクトリメソッドでしょう。

```kotlin
class User private constructor(val nickname: String) {
    companion object {
        fun newSubscribingUser(email: String) =
        	User(email.substringBefore('@'))
    }
}
```

https://pl.kotl.in/Nrf4-jX5z

:smile:「へぇ。ファクトリは基本ここに書く感じだね。」

### 通常のオブジェクトとしてのコンパニオンオブジェクト
コンパニオンオブジェクトの名前を省略した場合は、*Companion* というデフォルトの名前が付けられます。

:smiley:「へぇ。」

# 第 5 章 ラムダを使ったプログラミング
### スコープ内の変数アクセス
Kotlin と Java との重要な違いの 1 つは、Kotlin では、*final* 変数への参照だけに限定されていないことです。ラムダ内から変数を変更することもできます。

```kotlin
fun printProblemCount(responses: Collection<String>) {
    var clientErrors = 0
    var serverErrors = 0
    responses.forEach {
        if (it.startsWith("4")) {
            clientErrors++
        } else if (it.startsWith("5")) {
            serverErrors++
        }
    }
    println("$clientErrors client errors, $serverErrors server errors")
}
```

https://pl.kotl.in/cVek9ZGFV

例の prefix、clientErrors、serverErrors などのラムダから参照される外部変数は、ラムダによって**キャプチャ（capture）されている**と表現されます。

:grinning:「へぇ。」

### 遅延コレクション操作・シーケンス操作の実行
*map* や *filter* といった関数は、中間のコレクションを**先行評価して**（eagerly）作成します。つまり、各ステップの中間結果は一時的なリストに保持されます。**シーケンス**（sequence）という別の方法を使うことで、そのような一時オブジェクトを生成しない計算を実行できます。

原則として、**大きな**コレクションに対してチェインした操作を行うときには、シーケンスを使用します。

```kotlin
print(listOf(1, 2, 3, 4).asSequence().map {it * it}.find {it > 3})
```

https://pl.kotl.in/AXEwL9p37

この例で注目すべき重要なことは、処理が実行される順番です。単純な手法では、最初に各要素に対して *map* 関数を呼び出してから、その結果の各要素に対して *filter* 関数を呼び出します。
シーケンスにおいては、すべての操作が各要素に順番に適用されます。最初の要素が処理され、2 番目の要素が処理され、3 番目以降についても同様です。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-sequence.html

:open_mouth:「へぇ。Kotlin Collectionってシーケンシャルじゃなかったんだ。」

### *with* 関数
同じオブジェクトに対してその名前を繰り返すことなく複数の操作をするために使える特別な構文があります。

```kotlin
fun alphabet(): String {
    val stringBuilder = StringBuilder()
    return with(stringBuilder) {
        for (letter in 'A'..'Z') {
            this.append(letter) // 明示的に this を使ってレシーバのメソッドを呼び出す
        }
        append("\nNow I know the alphabet!") // this なしでメソッドを呼び出す
        this.toString() // ラムダから値を返す
    }
}
```

https://pl.kotl.in/VGxYgj2wA

*with* 関数は、最初の引数を 2 番目の引数のラムダの**レシーバ**（receiver）に変換します。このレシーバは、明示的に *this* 参照を用いて参照できます。通常は *this* 参照を省略し、追加の修飾子なしで、そのメソッドやプロパティを参照できます。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/with.html

:grin:「へぇ。*StringBuffer* にいくつも *append* することあるから使えそう。」

### *apply* 関数
*apply* 関数は、*with* とほぼ同じ動きをします。唯一の違いは、*apply* は常に引数の値として渡されたオブジェクト（つまり、レシーバオブジェクト）を返すことです。

```kotlin
fun alphabet() = StringBuilder().apply {
    for (letter in 'A'..'Z') {
        append(letter)
    }
    append("\nNow I know the alphabet!")
}.toString()
```

https://pl.kotl.in/4I3aZmaeO

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/apply.html

:grin:「へぇ。*apply* って名前のイメージ通りですき。」

# 第 6 章 Kotlin の型システム
### 安全キャスト

*as?* 演算子は、指定された方にキャストしようとして、値がその方ではない場合に *null* を返します。安全キャストを使う一般的なパターンの 1 つは、エルビス演算子と組み合わせることです。

```kotlin
class Person(val firstName: String, val lastName: String) {
    override fun equals(o: Any?): Boolean {
        val otherPerson = o as? Person ?: return false
        return otherPerson.firstName == firstName &&
        	   otherPerson.lastName == lastName
    }
    override fun hashCode(): Int =
    	firstName.hashCode() * 37 + lastName.hashCode()
}


fun main() {
    val p1 = Person("Dmitry", "Jemerov")
    val p2 = Person("Dmitry", "Jemerov")
    println(p1 == p2)
    println(p1.equals(42))
}
```

このパターンを使えば。変数が適切な型を持っているかをチェックし、それをキャストし、型が正しくない場合は *false* を返すといったことを、同じ式の中で簡単に行えます。

https://pl.kotl.in/FBwFdG5RD

https://kotlinlang.org/docs/typecasts.html

:grin:「へぇ。*Java* よりだーいぶ簡潔。スマートキャストが効いてるのが Good 」

### 非 *null* 表明
2 つの感嘆符というのは、いささか乱暴に見えるかもしれません。コンパイラに対して叫んでいるようにも見えますが、意図的なものなのです。Kotlin の設計者は、コンパイラによって検証できない non-null assertion を使わない、より優れた解決策へといざなっているのです。

心に留めておくべき注意点が、もう 1 つあります。*!!* を用いて例外が起きた場合、スタックとレースは例外がスローされた場所のしきではなく行番号を示します。どの値が *null* なのかを明確にするために、同じ行で複数の *!!* を使うことは避けてください。

```kotlin
person.company!!.address!!.country
```

この行で例外が発生した場合、*null* なのが *company* なのか *address* なのかを判別できません。

:laughing:「へぇ。そんな設計思想があったのか。」

### *let* 関数
*let* 関数は、*null* 許容型の式を扱いやすくします。セーフコールとともに使えば、式を実行し、その結果が *null* であるかチェックをして、変数に保持するといったことがすべて 1 行の簡潔な式で行えます。
最も一般的な用法の 1 つは、*null* 非許容型の引数をとる関数に *null* 許容型の引数を渡さなければならない場合です。

```kotlin
getTheBestPersonInTheWorld()?.let { sendEmailTo(it.email) }
```

複数の値が *null* であるかをチェックする必要がある場合は、ネストされた *let* 呼び出しを使って処理できます。しかし、そういった場合は、たいていコードが冗長になり、追うのが難しくなります。一般的には、通常の *if* 式を使って、すべての値のチェックを一緒にしてしまった方が簡単になるでしょう。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html

:thinking: 「うん。いわゆる *guard let* もやめた方がいいということかな。」

### *Unit* 型
*Void* ではなく *Unit* と違う名前にしたことを不思議に思うかもしれません。*Unit* という名前は、関数型言語において伝統的に「ただ 1 つのインスタンス」を意味するために使われています。
そして、これはまさに Kotlin の *Unit* と Java の *void* の違いなのです。

:thinking:「うん、よくわからない。」

### 読み取り専用コレクションとミュータブルコレクション
コレクションのインタフェイスを扱う際に留意すべき重要な点は、**読み取り専用コレクションが、必ずしもイミュータブルではない**ということです。読み取り専用インタフェイス型のコレクションを参照する変数があっても、同じコレクションへの数ある参照の 1 つに過ぎないということです。
コレクションに対する別の参照を持つコードを呼び出し、それを並列に走らせた場合、コレクションの作業中に他方のコードによってコレクションが変更される場面に出くわすかもしれません。それゆえ、**読み取り戦勝コレクションはスレッドセーフではない**ことの理解が不可欠です。

:hushed:「へぇ。読み取り専用コレクションはイミュータブルで、スレッドセーフって勝手にイメージしてたからちょっとビックリ。」

# 第 7 章 演算子オーバーロードとその他の変換の規約
### 二項演算子のオーバーロード
演算子のオーバーロードに使われているすべての関数には、*operator* というキーワードを付ける必要があります。これは規則に対応する実装として関数を利用することを意図しており、たまたま同じ名前の関数を定義してしまったわけではないということを明確にしています。

https://kotlinlang.org/docs/operator-overloading.html

:hushed:「へぇ。*operator fun invoke* をなんとなしに使っていたけど、そんな意味が。」

### 委任プロパティを使う
**遅延初期化**（lazy initialization）は、最初にオブジェクトが参照されたときに、初めてそのオブジェクトの一部を生成させる一般的なデザインパターンです。データの初期化処理が大きなリソースを消費し、オブジェクトの使用中、常にそのデータが必要ではない場合に、この遅延初期化が役立ちます。

```kotlin
class Person(val name: String) {
    private val _emails: List<Email>? = null
    
    val emails: List<Email>
    	get() {
            if (_emails == null) {
                _emails = loadEmails(this)
            }
            return _emails!!
        }
}


fun main() {
    val p = Person("Alice")
    println(p.emails)
    println(p.emails)
}
```

ここでは、いわゆる**バッキングプロパティ**（*backing property*）というテクニックを使います。まず、*_emails* という値を格納するプロパティと、それとは別の *emails* という *_emails* への読み取りアクセスを提供するプロパティを実装します。*_emails* は *null* 許容型、*emails* は *null* 非許容型と、これらのプロパティの型はことなっているので、2 つのプロパティを使う必要があります。
しかし、このコードは少し面倒です。遅延プロパティがいくつもある場合、コードがどれくらい長くなるだろうかと想像してみてください。そのうえ、スレッドセーフではないため、常に正しく動くとは限りません。

このコードは、委譲プロパティをつかうことで、はるかにシンプルになります。

```kotlin
class Person(val name: String) {
    val emails by lazy { loadEmails(this) }
}
```

*lazy* 関数は、適切なシグネチャの *getValue* という名前のメソッドを持つオブジェクトを返すので、*by* キーワードと一緒につかうことで、委譲プロパティを生成できます。*lazy* の引数は、値を初期化するために呼び出されるラムダです。*lazy* 関数はデフォルトでスレッドセーフです。

:open_mouth:「へぇ。ボイラープレートも排除できるうえ、スレッドセーフなのは強いな。」

# 第 8 章 高級関数
### インライン関数
通常、ラムダは無名クラスにコンパイルされます。しかし、これはラムダ式を使う度に余分なクラスが作成されることを意味しています。ラムダがいくつかの変数をキャプチャすると、新しいオブジェクトがすべての呼び出しで作成されます。それによって実行時のおあーばーヘッドが発生し、同じコードを直接実行する関数よりもラムダを使用する実装の効率が低下してしまいます。

*inline* 修飾子で関数をマークすると、コンパイラはこの関数を使用するときには関数呼び出しを生成せず、代わりに関数のすべての呼び出しをその関数を実装する実際のコードに置き換えます。
関数を *inline* で宣言すると、その本体はインライン展開されます。言い換えると、通常の呼び出しの代わりに、関数が呼び出される場所に関数の本体が直接置換されます。

```kotlin
inline fun <T> synchronized(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
        return action()
    }
    finally {
        lock.unlock()
    }
}

fun foo(l: Lock) {
    println("Before sync")
    synchronized(l) {
        println("Action")
    }
    println("After sync")
}

fun main() {
    val l = Lock()
    foo(l)
}
```

同じバイトコードにコンパイルされる同等のコードは次の通りです。

```kotlin
fun __foo__(l: Lock) {
    println("Before sync")
    l.lock()
    try {
        println("Action")
    }
    finally {
        l.unlock()
    }
    println("After sync")
}
```

インライン展開は、*synchronized* 関数の実装だけではなく、ラムダ式にも適用されることに注意してください。ラムダから生成されたバイトコードは、呼び出し関数の定義の一部となり、関数インタフェイスを実装する無名クラスにはラップされません。

https://kotlinlang.org/docs/inline-functions.html

:head_bandage:「へぇ。これだけ見ると、漏れなく *inline* 展開をした方がよさそうだけど、(次項を読むと)実際はそうではないみたい。」

### いつ、インラインとして関数を宣言することを決定するか
*inline* キーワードの利点について学んだので、コードベース全体を通して *inline* を使って、より速く実行できるようしたくなったかもしれません。結論から言うと、これはよい考えではありません。*inline* キーワードを使用すれば、ラムダを引数として取る関数ではパフォーマンスが向上する可能性があります。しかし、それ以外の場面については、さらなる計測と調査が必要です。
ラムダを引数に持つ関数をインライン展開することは有益です。第一に、インライン展開で回避するオーバーヘッドはより重要な意味を持っています。呼び出しだけでなく、各ラムダの追加クラスとラムダのインスタンスのオブジェクトの作成を抑えます。第二に、現在のところ、JVM は呼び出しとラムダを介して常にインライン展開を実行できるほどスマートではありません。

:thinking:「へぇ。高階関数のときは検討すればいい感じね。」

### インライン化されたラムダをリソース管理に使用する
Kotlin は、Java 7の *try-with-resources* と同等の構文を備えていません。同じ絡子は、関数型を引数として持つ関数を通して、ほとんどシームレスに実行できるからです。その関数は *use* 関数と呼び誰、Kotlin 標準ライブラリに含まれています。

```kotlin
fun readFirstLineFromFile(path: String): String {
    BufferedReader(FileReader(path)).use { br ->
    	return br.readLine()
    }
}
```

*use* 関数は、*Closable* インターフェイスを実装しているリソース上で呼び出される拡張関数です。引数としてラムダを受取ります。この関数はラムダを呼び出し、ラムダが正常に終了するか例外スローするかに関わらず、リソースが閉じられることを保証します。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html

:hugging:「へぇ。*try-with-resources* は利用頻度高いから *use* はよく使うことになりそう。」

# 第 9 章 ジェネリクス
### ジェネリック型パラメータ
Java とは異なり、Kotlin では型引数は常に明示的な指定か、あるいはコンパイラによる推論が必須です。
そのため、値がセットや他のオブジェクトではなくリストであることをチェックするには、どうしたらよいのでしょうか。**スター投影**（star projection）という特別な構文を使用することで可能になります。

```kotlin
if (value in List<*>) { ... }
```

:grinning:「へぇ。Java でいうところの List<?> にあたるのかな。」

### クラス、型、サブタイプ
時折、**型**と**クラス**という用語は同じものとして使ってきましたが、実際には別物です。
最も単純なケースとしては、非ジェネリッククラスでは、クラスの名前が型として直接使用されます。 `var x: String?` のような null 許容型の宣言に同じクラス名を使用できることに注意してください。これは、Kotlin の各クラスが少なくとも 2 つの型を構築するのに使用されることを意味します。

サブクラスとサブタイプの違いは、ジェネリック型について説明するときに特に重要になります。「`List<Any>` を期待する関数に対して、型 `List<String>` の変数を渡すことは安全かどうか？」という問いは、サブクラスの観点からは「`List<String>` は、`List<Any>` のサブクラスなのだろうか？」と言い換えることができます。`MuttableList<String>` は `MuttableList<Any>` のサブクラスとして扱うことはできません。その逆も安全ではないことは明らかです。つまり、`MuttableLisy<Any>` は `MuttableList<String>` のサブタイプではないということです。
2 つの異なる任意の型AとBにおいて、`MutableList<A>` が `MutableList<B>` のサブタイプでもスーパータイプでない場合に、ジェネリッククラス `MutableList` は、型パラメータについて**不変**（imnvariat）であるといいます。

:thinking: 「なるほど。あまりそこらへん意識して区別できてなかったし、ジェネリクスが入るとクラスの考え方が難しいな。」

### 共変と反変
Kotlin の List インタフェースは、読み取り専用コレクションを表現しています。AがBのサブタイプなら、`List<A>` は `List<B>` のサブタイプです。このようなクラスやインタフェースは、**共変**（covariant）と呼ばれます。
共変なクラスは、「AがBのサブタイプである場合、`Producer<A>` は `Producer<B>` のサブタイプである」が成り立つようなジェネリッククラスです。

**反変**（contravariance）の概念は、共変の鏡として考えることができます。反変クラスにとって、サブタイピングの関係は、型引数として使用されるクラスのサブタイピングの関係と正反対です。

クラスメンバの宣言における型パラメータの使用は、**in** と **out** のポジションに分けることができます。

| 共変 | 反変 | 不変 |
| ---| --- | --- |
| `Producer<out T>` | `Consumer<in T>` | `MutableList<T>` |
| **クラスのサブタイピングは維持**：`Producer<Cat>` は `Producer<Animal>` のサブタイプ | **サブタイプは逆**：`Consumer<Animal>` は `Consumer<Cat>` のサブタイプ | **サブタイプなし** |
| T は out ポジションだけ | T は out ポジションだけ | T はどこでも |

https://kotlinlang.org/docs/generics.html

:smiley:「へぇ。Java でいう extend、super が in、out ってことか。」

#第 10 章 アノテーションとリフレクション
### アノテーションの適用
アノテーションの引数を指定する構文は、Java とは少し違います。

- **クラスをアノテーションの引数として指定する**ためには、`@MyAnnotation(MyClass:cass)` のようにクラス名の後ろに *::class* を付けます
- **別のアノテーションを引数として指定する**ためには、アノテーションの前に @ を付けません。例えば、前の例の ReplaceWith はアノテーションですが、Deprecated アノテーションの引数として指定するときには @ を使いません。
- **配列をアノテーションの引数として指定する**ためには、`@RequestMapping(path = arrayOf("/foo", "/bar"))` のように、*arrayOf* 関数を使います。アノテーションクラスが Java 内に宣言されている場合は、value という名前の引数は必要な時に vararg 引数へど自動で変換されます。したがって、*arrayOf* 関数を使うことなく引数を渡せます。

:rolling_eyes:「へぇ。Java でいう *.class* が *::class* なのかな。」

### アノテーションの対象
アノテーションを付ける要素は**使用場所対象**（use-site target）宣言を使って指定します。対象の指定は、@ とアノテーション名との間に置いて、転んで名前と区切ります。

- *property*：この使用場所対象を使って Java のアノテーションは適用できない
- *field*：プロパティ用に生成されるフィールド
- *get*：プロパティの getter
- *set*：プロパティの setter
- *receiver*：拡張関数や拡張プロパティのレシーバ引数
- *param*：コンストラクタ引数
- *setparam*：プロパティの setter の引数
- *delegate*：デリゲートプロパティのデリゲートインスタンスを保持するフィールド
- *file*：ファイル内に宣言されたトップレベル関数やプロパティを含むクラス

https://kotlinlang.org/docs/annotations.html

:grin:「へぇ。」

### アノテーションを使って Java の API を制御する
Kotlin では、Kotlin で書かれている宣言をどのように Java のバイトコードにコンパイルし、Java の呼び出し側からどのように見えるかを制御するさまざまなアノテーションが提供されています。

- *@JvmName* は、Kotlin での宣言から生成される Java のメソッドやフィールドの名前を変更する
- *@JvmStatic* をメソッドに適用することで、オブジェクト宣言やコンパニオンオブジェクトのメソッドが static な Java のメソッドとして見えるようになる
- *@JvmOverloads* は、引数のデフォルト値を持った関数に対してオーバーロードメソッドを生成するように Kotlin のコンパイラに伝える
- *@JvmFiled* をプロパティに適用することで、プロパティが getter や setter のない public な Java のフィールドとして見えるようになる

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/

:thinking:「なるほど。ここらへんは、実際に Java のバイトコードにしたら分かりやすいかも。」

### アノテーションの引数としてのクラス
*KClass* 型は、Java の *java.lang.Class* 型に相当する Kotlin の型で、Kotlin のクラスへの参照を保持するために使います。*KClass* の型パラメータは、この参照によって Kotlin のどのクラスを参照できるかを指定しています。

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-class/

:relieved:「へぇ。リフレクションで使えそう。使わない方が安全ではあるけど。」

### Kotlin のリフレクション
Kotlin のリフレクション API の主なエントリポイントは、クラスを洗わず *KClass* です。*KClass* は、クラスやスーパークラスなどに含まれるすべての宣言を列挙して参照するために使うことができます。
*KCallable* は、関数とプロパティのスーパーインタフェースなのです。*call* メソッドが宣言されていて、それを使って対応する関数もしくはプロパティの getter を呼び出すことが可能です。
*KFunction1* のような方は、引数の数が違う関数を表しています。それぞれの型は *KFunction* を継承し、対応する数の引数を持った *invoke* という　*KFunction2* には `operator fun invoke(p1: P1, p2: P2): R` が宣言されています。これらの関数は**コンパイラによる生成型**（synthetic compiler-generated types）ですが、その宣言は *kotlin.reflection* パッケージ内にはありません。つまり、そのインタフェースは、任意の数の引数を持つ関数に対して使えるということです。

![aws.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/05b77e43-80b4-3392-eaa6-277764ac4293.png)

:relaxed:「へぇ。Kotlin のリフレクションはずいぶん細かく痒いところに手が届く感じあるな。」

#第 11 章 DSL の作成
### API から DSL へ
**ドメイン固有言語**（Domain-Specific Language）を使って、Kotlin のクラスで表現豊かな API を設計する方法について説明します。
洗練された API を構築するために利用できる Kotlin の機能には、例えば、拡張関数、中置呼び出し、ラムダ構文のショートカット、演算子のオーバーロードなどがあります。

| 通常の構文 | 洗練された構文 | 使われている機能 |
| --- | --- | --- |
| StringUtil.capitalize(s) | s.capitalize() | 拡張関数 |
| 1.to("one") | 1 to "one" | 中置呼び出し |
| set.add(2) | set += 2 | 演算子オーナーロード |
| map.put("key") | map("key") | get メソッド規約 |
| file.use({ f -> fread() }) | file.use { it.read() } | 括弧の外側のラムダ |
| sb.append("yes")<br>sb.append("no") | with (sb) {<br>append("yes")<br>append("no")<br>} | レシーバー付ラムダ |

:blush:「まあ、Kotlin のイディオムでこんな簡潔で自由に表現できるよ！ってことかな。」

### invoke 規約による柔軟なブロックのネスト
*invoke* メソッドが *operator* 修飾子付きで定義されているクラスは、関数のように呼び出せます。

```kotlin
class Greeter(val greeting: String) {
    operator fun invoke(name: String) {
        println("$greeting, $name")
    }
}

fun main() {
    val bavarianGreeter = Greeter("Servus")
    bavarianGreeter("Dmitry")
}
```

https://pl.kotl.in/PrXDTo2Jl

このコードは、Greeter クラスに *invoke* メソッドを定義しています。このメソッドによって、Greeter インスタンスが関数であるかのように呼び出すことができるのです。内部では、`bavarianGreeter("Dmitry")` の式は、`bavarianGreeter.invoke("Dmitry")` のメソッド呼び出しにコンパイルされます。

:wink:「へぇ。省略は楽だけど、文脈に気を付けて使わないとクラス利用者にミスリードさせちゃいそう。」

#おわりに
Kotlin の生の思想に触れることができる良本でした。
また、「Kotlin の味見」や「Kotlin を愛でる」など、表題にさえも Kotlin のコンセプトやイメージみたいなものが詰まっており、Kotlin に対する愛を随所に感じました。