今から始める Kotlin (1)

最近 iPhone から Android スマートフォンに機種変更したので Android 用アプリを開発しようと Kotlin の学習を始めてみました。
この記事は学習メモになります。

もっとも、メモとは言いつつ、Kotlin のサイトを引用している個所が多々あるので、最新情報は [こちら](https://kotlinlang.org/docs/reference/basic-syntax.html) を参照してください。


## Basic Syntax

基本的な文法ということで、[Basic Syntax](https://kotlinlang.org/docs/reference/basic-syntax.html) を頭から目を通してみます。

### Package definition

Java と同じ。

詳細は [Packages](https://kotlinlang.org/docs/reference/packages.html) 参照。

```kotlin
package my.demo
```

### import

Java と同じ？
章を進めることで違いがあるかも。

```kotlin
import kotlin.text.*
```

### Program entry point

Java とは異なり、アクセス修飾子や引数は無くても問題ない。

```kotlin
fun main() { /* 処理 */ }
```

### Functions

Kotlin ではメソッドではなくファンクション（関数）。
TypeScriptなどと同じく、型指定が後にくるタイプ。
return が省略できるかはきっと後に出てくる。

詳細は [Functions](https://kotlinlang.org/docs/reference/functions.html) 参照。

```kotlin
fun sum(a: Int, b: Int): Int {
    return a + b
}
```

ファンクションが意味のある値を返さない場合は `void` ではなく `Unit` を指定するか、戻り値の型を省略する。

```kotlin
fun printSum(a: Int, b: Int): Unit {
    println("sum of $a and $b is ${a + b}")
}

// or

fun printSum(a: Int, b: Int) {
    println("sum of $a and $b is ${a + b}")
}
```

### Variables

変数の定義。`final` や `const` みたいな修飾子は不要なもののタイプミスしそう。

`val` は再代入不可能な変数。`var` は再代入可能な変数。

詳細は [Properties and Fields](https://kotlinlang.org/docs/reference/properties.html) 参照。

```kotlin
val a: Int = 1
var b: Int = 5

a = 2 // Val cannot be reassigned
b = 6
```

今時の言語なので型を省略しても型推論が行われる。

なお、`val` は再代入不可能かどうかであり`immutable` であるかは別問題です。

```kotlin
// これはコンパイルできる
val foo = mutableListOf("foo", "bar")
foo.add("boo")

// これはコンパイルエラー（listOfの場合はimmutableなのでadd関数自体が存在しない）
val foo = listOf("foo", "bar")
foo.add("boo") // Unresolved reference: add
```

### Comments

Javaと代り映えはしないものの、コメントのネストができる！

詳細は [Documenting Kotlin Code](https://kotlinlang.org/docs/reference/kotlin-doc.html) 参照。

```kotlin
/* The comment starts here
/* contains a nested comment */     
and ends here. */
```

コメントのネストが必要な場面って既存のコードをコメント含めて**まるっとコメントアウトしたい**場合でしょうか。IDE の機能を使って、選択範囲の行頭に `//` を付けるでもよい気もしますが、`diff` 取った時の差分の違いがメリットかもしれません。

### String templates

文字列テンプレート機能は標準搭載！
式も記述可能。

詳細は [String templates](https://kotlinlang.org/docs/reference/basic-types.html#string-templates) 参照。

```kotlin
var a = 1
// simple name in template:
val s1 = "a is $a" 

a = 2
// arbitrary expression in template:
val s2 = "${s1.replace("is", "was")}, but now is $a"
```

文字列テンプレート内の式で使用しているダブルクォーテーションはエスケープ不要なのは良いですね。

### Conditional expressions

条件式。いわゆる「if文」
Kotlin の特徴は「式」扱いなので、サンプルコードのような記述もできる。

詳細は [If Expression](https://kotlinlang.org/docs/reference/control-flow.html#if-expression) 参照。

```kotlin
fun maxOf(a: Int, b: Int) = if (a > b) a else b
```

### Nullable values and null checks

学習し始めたばかりなので何とも言えないですが、実行時の `NullPointerException` がかなり抑えられると思われます。

詳細は [Null Safety](https://kotlinlang.org/docs/reference/null-safety.html) 参照。

Kotlin は変数宣言時に型を指定した場合 `null` は許容されず、次のようなコードはコンパイルエラーなります。

```kotlin
var foo: String = null // Null can not be a value of a non-null type String
```

もし `null` を許容する場合は型名の後に `?` を付けます。

```kotlin
var foo: String? = null
```

次のような場合は、型の推論にも伝播されます。

```kotlin
fun parseInt(str: String): Int? {
    // ...
}

val x = parseInt(arg1) // val x: Int? と同じ扱い
```

もう少し踏み込むと、`null` を許容する場合でも次のコードはコンパイルエラーになります。

```kotlin
var foo: String? = null
println(foo.isEmpty()) // Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
```

メソッド呼び出し時の変数名の後ろに `?` を付けることで、コンパイルエラーとはならなくなります。実行時に変数が `null` の場合はメソッド呼び出しは行われず `null` が返されます。

```kotlin
var foo: String? = null
println(foo?.isEmpty())
// この場合、標準出力には null が出力され、NullPointerException はスローされない。
```
上記を踏まえると、次のコードはコンパイルエラーとなります。

```kotlin
var foo: String? = null
var isEmpty: Boolean = foo?.isEmpty()
```

これは、コンパイル時に `foo?.isEmpty()` は `null` が確定しているにも関わらず、変数 `isEmpty` は `null` を許容していないからです。

これらの仕組みを駆使すると、だいぶ***ぬるぽ***は抑えられるのではないでしょうか。

### Type checks and automatic casts

`is` 演算子を使って型チェックを行うと、自動的にキャストしてくれます。いわゆる*スマートキャスト*です。

詳細は [Type Checks and Casts: 'is' and 'as'](https://kotlinlang.org/docs/reference/typecasts.html) 参照。

```kotlin
fun getStringLength(obj: Any): Int? {
    if (obj is String) {
        // `obj` is automatically cast to `String` in this branch
        return obj.length
    }

    // `obj` is still of type `Any` outside of the type-checked branch
    return null
}
```
Kotlin 1.3 以降ではこの*スマートキャスト*が更に賢くなっているようですが、今は割愛します。

### for loop

いわゆる `for` 文。ちょっと面白いのがインデックスの取得方法。

詳細は [For Loops](https://kotlinlang.org/docs/reference/control-flow.html#for-loops) 参照。

```kotlin
// Java でいうところの for-each
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
    println(item)
}
```

インデックスを使った繰り返し処理を行いたい場合はこちら。

```kotlin
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
    println("item at $index is ${items[index]}")
}
```

更にこんな書き方もある模様。Pythonで言うtuple的なものが存在する？（きっと後から出てくる）

```kotlin
for ((index, value) in array.withIndex()) {
    println("the element at $index is $value")
}
```

### while loop

`while` 文。Java と比較しても代り映えしない。

詳細は [While Loops](https://kotlinlang.org/docs/reference/basic-syntax.html#using-a-while-loop) 参照。

```kotlin
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items.size) {
    println("item at $index is ${items[index]}")
    index++
}
```

### when expression

Java の switch 文に相当するものだが、もう少し賢い。
Java の switch 文とは異なり評価対象の値の型は制限が無く、評価方法も自由度が高い。更に `break` を使った中断も不要。

詳細は [When Expression](https://kotlinlang.org/docs/reference/control-flow.html#when-expression) 参照。

```kotlin
when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}
```

それにしても Java はなぜ `break` しないとダメって仕様を引き継いだんでしょうかね。

詳細のリンク先を読むと `when expression` の凄さが理解できるかと思います。

### Ranges

繰り返し処理などに使える数列を生成する構文です。
ざっくり言えば、`for( int i = 0; i < 10; i++)` を `for(i in 0..9)` で記述できるような仕組みです（`0..9` の部分が `Range`）。


詳細は [Ranges](https://kotlinlang.org/docs/reference/ranges.html) 参照。


記述方法は簡単で、インクリメントしたい場合は `開始値..終了値` と記述し、デクリメントしたい場合は `開始値 downTo 終了値` と記述します。

デフォルトでは `1` 刻みに値が変化しますが、`step` を指定することで刻み幅を変えることができます。

`for (i in 1..9 step 3)` と指定した場合、 `i` の値は `1, 4, 7` となり、`for (i in 9 downTo 1 step 3)` と指定した場合、`i` の値は `9, 6, 3` となります。

```kotlin
for (i in 1..9 step 3) print(i) // 1, 4, 7
for (i in 9 downTo 1 step 3) print(i) // 9. 6, 3
```

なお、片端入れの構文も存在します。

`for( int i = 0; i < 10; i++)` は `for(i in 0 until 10)` と書き換えることができますが、個人的には両端入れが分かりやすいです。

### Collections

集合。 Java の `List` や `Map` など。

詳細は [Collections overview](https://kotlinlang.org/docs/reference/collections-overview.html) 参照。

`in` 演算子は Kotlin 固有ですが、Java の `Stream API`　的なことも可能です。

`in` 演算子の例

```kotlin
when {
    "orange" in items -> println("juicy")
    "apple" in items -> println("apple is fine too")
}
```

`Stream API`　的な処理。

```kotlin
val fruits = listOf("banana", "avocado", "apple", "kiwifruit")
fruits
  .filter { it.startsWith("a") }
  .sortedBy { it }
  .map { it.toUpperCase() }
  .forEach { println(it) }
```

## Kotlin のここまでのまとめ

ここで挙げた構文を見る限り、Python 、 TypeScript 、Groovy といった言語をかじったことがある方はすんなり受け入れられそうな印象でした。

振り返ってみると、クラスとかインターフェースの話が無いので、次回はクラスやインターフェースに触れたいと思います。