Kotlinプログラミングを読んで気になった箇所メモ ①

備忘録用。

[Kotlinプログラミング](https://www.amazon.co.jp/Kotlin%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Josh-Skeen/dp/4798160199/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=kotlin%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1567736071&s=gateway&sr=8-1)を読んで気になったKotlinの文法や仕様をアウトプット。
ちょっとだけ掘り下げて調べた箇所もあり。
本書の **2章 ~ ４章** まで。(1章は開発環境構築だったのでスキップ)
サンプルコードは本書から書き換えて記述している。

### Kotlinの変数・関数宣言の仕方

#### 変数

```kotlin
// 変数宣言キーワード 変数名:型定義 = 代入値
var age:Int = 20
```



#### 関数

```kotlin
// 可視性修飾子 関数宣言キーワード 関数名(関数パラメータ):戻り値の型{
//  ...
// }

private fun hello(name:String):String {
  return "Hello, $name san"
}
```


### 2章 変数と定数と型

#### 2.5 型推論

```kotlin
val playerName: String = "Estragon"
```

上記のような記述はInteliJだと `String` 部分が灰色となり、「冗長な記述をしている」のようなメッセージが出る。
これは、型宣言時に `String` のデータを代入しているため、コンパイラが型情報を推論しているため。

IntellJでは 変数名にマウスカーソルをあわせて `Command + Shift` で型情報を表示できる。


#### 2.6 コンパイル時定数

名前の通りプログラムをコンパイルするときにその変数が代入される。(mainや他の関数の変数は **実行時(runtime)** に代入される。
関数・クラスの外側に定義する。

String, Int等の基本型のみサポートされる。ほかだとコンパイル時という保証が得られない。


`const` 修飾子を使う。

```kotlin
const val MAX_EXPRERIENCE: Int = 5

fun main(args: Array<String>) {
  println(MAX_EXPRERIENCE) // 5
}
```

同パッケージの階層で同じ定数名は使えない。

`private`等の、アクセス修飾子を付けない限り、どこからでもアクセスできてしまう。
なので、むやみに乱用するとグローバル汚染が懸念される。


#### もっと知りたい？ KotlinにおけるJavaのプリミティブ型

Javaと違い、Kotlinは参照型しかない。プリミティブ型が無い。
ただし、コンパイラは可能であれば、Javaのバイトコードでプリミティブを使う。これはプリミティブ型のほうが性能が高いため。



### 3章 条件文



#### 3.8 範囲

範囲(range) をつかって一連の値を表現できる。 
 `..` を使うことで、範囲を表現できる。
`in`キーワードを使うことで、値が範囲に含まれているかチェックする。



`in 1..3` なら 1,2,3 が含まれる。

```kotlin
  println(2 in 1..3) // true
  println(4 in 1..3) // false
  for (i in 1..3) print(i) // 123
  for (i in 3 downTo 1) print(i) // 321
  for (i in 1..8 step 2) print(i) // 1357
```

文字の範囲チェックもできる。

```kotlin
println('c' in 'a'..'c') // true
println('d' in 'a'..'c') // false
```

Dateの範囲チェックもできたりする。(ただし、`downTo` 等の関数は使えないので注意)

```kotlin
val start = Date.valueOf("2019-01-01")
val end = Date.valueOf("2019-12-31")
println(Date.valueOf("2019-08-01") in start..end) // true
```

範囲(`..`)を使ってList生成したりはよく使いそう。

```kotlin
(11..15).toList().forEach({ i -> println(i) }) // 11 12 13 14 15
```

#### 3.9　when式

JavaでいうSwitch文。
3つ以上の分岐があるならwhenを使ったほうがキレイになる。

```kotlin
// 引数あり
val str = "hoge"
when (str) {
    "hoge" -> println("ほげ")
    "huga" -> println("ふが")
    else -> println("ぴよ")
}
```

```kotlin
  // 引数なし
  val str = ""
  val result = when {
      str == null -> "str is null"
      str.isEmpty() -> "str is Empty"
      str == "hoge" -> "ほげ"
      else -> "ぴよ"
  }
  println(result)
```



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

`$変数名`とすれば文字列の中に変数を埋め込めむことができる。
スペース等の区切り文字が無いもしくは、中で式を書きたいときは `${}` を使う。

```kotlin
println("私は" + name + "、" + age + "歳です。") // 私はマイク、20歳です。
println("私は$name、${age}歳です。") // 私はマイク、20歳です。

// 文字列テンプレートの中に式を書くこともできる
println("私は$name、${if (age >= 20) "成人" else "未成年"}です。") // 私はマイク、成人です。
```

### 4章 関数

#### 4.2 関数の解体

関数は `private` など明示的に指定しないとデフォルトで `public` とみなす。

#### 4.6 デフォルト引数

引数を指定されないときに使うデフォルト値

```kotlin
private fun calcTax(taxRate: Double = 0.10) {
    val price = 1000
    println("${price}円 の商品の消費税は ${price * taxRate}円です。")
}

calcTax() // 1000円 の商品の消費税は 100.0円です。
calcTax(0.08) // 1000円 の商品の消費税は 80.0円です。
```

#### 4.7 単一式関数

1つの式しか持たない関数は `{}` を省略して `=` で記述できる。

* 例1

```kotlin
private fun calcTax(price: Int = 1000, taxRate: Double = 0.10) {
    println("${price}円 の商品の消費税は ${price * taxRate}円です。")
}
```

↓

```kotlin
private fun calcTax(price: Int = 1000, taxRate: Double = 0.10) =
    println("${price}円 の商品の消費税は ${price * taxRate}円です。")
```


* 例2

when文も１つの式扱いなので `=` で記述できる。

```kotlin
private fun rate(score: Int): String {
    return when (score) {
        100 -> "great!"
        in 40..99 -> "good"
        else -> "bad.."
    }
}
```


```kotlin
private fun rate(score: Int): String = when (score) {
    100 -> "great!"
    in 40..99 -> "good"
    else -> "bad.."
}
```

#### 4.8 Unit関数

Javaでいう voidに近い、でも厳密には違うらしい。

* void: 何も返さない
* Unit: 値を返さない関数

Unitだと何も返さないジェネリックス関数を書けるメリットになるらしい。
あまりピンとこない...17章で詳しく説明されるので一旦保留。


#### 4.9 名前付き引数

下記の例は、同じ関数を同じ引数で呼び出している。

```kotlin
// 名前付き引数
introduce(from = "大阪", name = "太郎", age = 20)

private fun introduce(name: String, age: Int, from: String) {
    println("私は $name、 $age 歳です。出身は $from です。")
}
```

* 名前付き引数は関数ヘッダの並びと関係無い順番で渡せる。
* どこの引数がどの関数パラメータに値を提供しているのかが分かるので、コードが明瞭になる。

#### 4.10 Nothing関数

関数が正常終了しないことを保証する。つまりExceptionが発生する関数。
例外をThrowする等の理由で決して呼び出し側に戻らない関数。

標準ライブラリにTODO関数が入っており、これの返却型はNothing。
`NotImplementedError` は発生する。

```kotlin
TODO("TODO") // NotImplementedError
println("Hello World") // 実行されない
```

### 参考文献

* [Kotlinプログラミング](https://www.amazon.co.jp/Kotlin%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Josh-Skeen/dp/4798160199/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=kotlin%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1567736071&s=gateway&sr=8-1)
* [Kotlin公式Does](https://kotlinlang.org/docs/reference)