Kotlinの基本。vol.1

## 目的
Kotlinを使用している中で、本当に基礎的なことが抜けているなと感じることが何度かあった。
本当に基礎から学び直すために、アウトプットする。

対象: **Javaを学んだことがある** or **プログラム言語に触ったことがある**

## Kotlin

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261466/9f66f23f-1c46-94bc-436b-be1cd2372906.png)

 
### 特徴

 - JVM上で機能
 - 静的なNull安全が保証
 - アンドロイド公式開発言語として採用
 - Javaとの互換性あり
 - サーバでも使用されている

---

KotlinはJVM上で機能する、静的なNull安全が保証された言語になっています。特に、アンドロイド公式言語として、採用されたこともあり有名になったように感じました。また、Javaとの互換性があり、これまで書かれていたアンドロイド用のJavaコードを流用することができることから、他の言語に比べて移行か簡単であるということも非常に大きな点かと思います。

Javaよりもかなり簡潔にかけ、Null安全などの陥りやすいミスを未然に防いでくれていることからかなりいい言語だと感じました。
最近では多くの企業(Yahoo!, Line, Abema, Rettyなど)がKotlinを採用するなど、業界からも注目を浴びています。

主にAndroidで使用されるとも書きましたが、サーバサイドでKotlinを採用する場合もあり、様々な場面で生きてくる言語かと思います。

## 実行環境

今回Kotlinの文法などに着目するためブラウザで機能するKotlin実行環境[プレイグラウンド](https://play.kotlinlang.org/)を使用する。
使い方は、このリンクにアクセスするだけ。
AndroidStudioのインストール方法などに関してはここでは解説しない

## 基礎基礎
### お品書き

- 変数の定義
- Nullについて
- 関数の定義
- if
- for
- when
- コレクション

### 変数の定義
``` Kotlin
// 変数の型推定をしてくれるので、特に指定せずに変数を宣言できる
var x // 変更可能な変数
val y // 変更不可能（読み取り専用）な変数の宣言

// もちろん型を合わせた宣言も可能
val i: Int = 4 // 結果: 4
val f: Float = 4.0 //  結果: 4.0

// JavaだとInt -> floatは自動でキャストされていたが、Kotlinでは宣言する必要がある
val d: Double = 10 // 結果: エラー 

// The integer literal does not conform to the expected type Double
val d: Double = 10.0

// キャストは基本toHoge()を使用する
var e: Int = 10
var l: Long = e.toLong()
```

### Nullについて

``` Kotlin
// Kotlin上でNullを使用する場合は型宣言時に使用すると記述する必要がある
var n: Double = null
// -> Null can not be a value of a non-null type Double

// Null使用時には型の後ろに「?」をつける
var n: Double? = null // ok

// 返り値などでNull許容をする場合も同じように?をつける
// 関数の項目で説明
```
### 関数の定義

``` Kotlin
// 基本的な関数の書き方は以下のようになっている。
// fun 関数名(仮引数: 引数の型): 返り値の型 {}

fun Sum(a: Int, b: Int): Int {
    var sum: Int = a + b
    return sum
}

// 返り値を持たない場合(Javaだとvoid型)はUnitを返り値とする
fun Sum(a: Int, b: Int): Unit {
    var sum: Int = a + b
    println(sum)
}

// 返り値が単体、もしくは式の場合省略が可能
fun Sum(a: Int, b: Int): Int = a + b
println(Sum(1,2)) // 結果: 3

// 引数のデフォルト設定が可能で、引数が指定されなかった場合には自動で補完される
fun Sum(a: Int = 1, b: Int = 2): Int = a + b
println(Sum(4)) // 結果: 6 -> 一つだけ引数を指定した場合は先頭引数だけに代入される

// 引数の名前をキーとして代入することも可能
fun Sum(a: Int = 1, b: Int = 2): Int = a + b
println(Sum(b = 7)) // 結果: 8

// エラー例

// 1
println(Sum(a = 4, 5)) // a =4 b = 5となってほしいが、ならない。
// -> 名前付き引数と位置指定引数を混在させることはできませんとエラー
// 名前付き引数として使用したい場合は後ろの引数とする必要がある。
println(Sum(4, b = 5)) // ok

// 2
fun Sum(a: Int = 1, b: Int): Int = a + b // aにのみデフォルト変数を宣言した
println(Sum(3)) // bに変数を代入したいが、できないのでエラー

fun Sum(a: Int, b: Int = 1): Int = a + b //デフォルト引数を指定する引数を後述することで解決
println(Sum(3)) // ok

// 可変長引数
// 複数の引数（数は決まっていない）を受け取りたい場合に使用できる
fun allSum(vararg values: Int): Int {
    var result = 0
    for (value in values) {
        result += value
    }
    return result
}   
println(allSum(1,2,3,4))
	
// 配列を可変長引数を使った関数のの引数として使いたい場合はスプレット演算子「*」を先頭につけるとできる 
val arr = intArrayOf(2,3,1,7)

println(allSum(*arr)) // 結果: 13
// println(allSum(arr)) 結果: エラー

// 配列と別の数字も同時に引数とできる
println(allSum(4, *arr, 3)) // 結果: 20



```
### 型チェックと自動キャスト
``` Kotlin
fun getStringLength(obj: Any): Int? {
  if (obj is String) { // is obj String? の文で非常に直感的に思える。
    // obj がStringならこの条件分の中ではobjは自動的にStringにキャストして扱われる(スマートキャスト)
    // そのため、Anyが持っていない.lengthを使用することができる
    return obj.length
  }

  // `obj` は型チェックが行われたブランチ外では、まだ`Any`型である
  return null
}
```
### if式
``` Kotlin
// if "式" のため、値を返すことができる
// ただし、必ずelseが必要となる。
val a = 10
var msg = if (a <= 5) {
        "aは5以下です"
    } else if (a <= 10){
        "aは10以下です。"
    } else {
        "aは10以上です。" //returnのように使える 
    }
println(msg) // 結果: aは10以下です。
```
### for式
``` Kotlin
    for (i1 in 1..3) println(i1) // 1 2 3
    for (i2 in 1 until 3) println(i2) // 1 2
    for (i3 in 3 downTo 1) println(i3) // 3 2 1
    for (i4 in 1..10 step 3) println(i4) // 1 4 7 10

// 特に書くことはないが、範囲などの指定がPythonとかに似ている気がする。かなり便利。

// for文などを用いる際にラベルを使用することができる。vol2で記載するラムダ式でも説明する
// 全てのfor文を終了する場合はラベル構文を用いる
    outer@ for (i7 in 1..3) {
        for (j2 in 1..3) {
            if(i7 * j2 > 5) break@outer // ここで呼ぶことによって outerラベルのfor文をbreakできる 
            print("${i7*j2} ")
        }
    }
```
### when式
``` Kotlin
// より直感的なswitch文のイメージ

val x = 1
when (x) {
    1 -> println("x: 1")
    2 -> println("x: 2")
    else -> println("else")
}

// 他と同じように式として値を返すことができる。
val y = when(x) {
    1 -> "x: 1"
    2 -> "x: 2"
    else -> "else"
}
println(y) // 結果: x:1

// is式を行うこともできる
val l: String = "abcdef"
val msg = when(l) {
    is String -> "This is String"
    else -> "Not String"
}

println(msg) // 結果: This is String
```
### コレクション
``` Kotlin

var array = arrayOf(1,2,3)
var array_int = intArrayOf(1,2,3)
    
var array_null: Array<String?> = arrayOfNulls(3)
var array_class = Array(3, {i -> i * 2})
println(array_class[2])
    
//変更不可能なコレクション
var list = listOf("あ","い","う")
var set = setOf("A","B","A","F","F")
var map = mapOf("First" to 1, "Second" to 2, "Third" to 3)

println(list) // [あ, い, う]
println(set) // 重複した物を除くコレクション  [A, B, F]
println(map) // キーを含むコレクション {First=1, Second=2, Third=3}
list[2] = 4 //結果: No set method providing array access


// 変更可能なコレクション
// mutableをつけてコレクションを宣言することで、後から変更することが可能になる。
var M_list = mutableListOf(1,2,3)
M_list[2] = 4
println(M_list)

```

## 終わりに
基本的なことは非常に多いため、備忘録的な気持ちでアウトプットしています。
そのため、今回をvol.1としましたが、基礎的なことを復習していき、vol.2も書こうと思います。
少しでも、Kotlinに興味が湧いた人がいれば嬉しいです。

## 参考
[公式リファレンス(日本語訳)](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/basic-syntax.html)