今からKotlin

ドワンゴで就業形インターンをしているコキチーズです。
主にAndroidエンジニアをやってます。

アドベントカレンダーの枠に入れてもらえたので
ドワンゴで学んだことを書こうかとも思ってましたが

ドワンゴの人が注目するチャンスでもあるので、ここではKotlinをワッショイしとくのもありなのでは？と思い2016年をKotlinの年とするべくKotlinの魅力を頑張って伝えたいと思います。

# Kotlinって？
KotlinはJetBrainsが作っているJVM上で動かせるプログラミング言語です。
JetBrainsが何かと言うとJava IDE界の神にも等しい存在です。
わかりやすく言うとプロ向けの開発現場でよく使われているIntelliJ IDEAと言う統合開発環境を制作しているところです。

Kotlinは2011年の夏に発表されたばかりで比較的新しい言語でもあります。

そもそもなんでJavaで書かず、またJVMで動く言語はClojure,Groovy,ScalaとかとかあるのにKotlinなのか

JavaのJVMという環境は広く普及していて最高のプラットフォームなんですが
言語としてのJavaが冗長でめんどくさいです。(個人的感想)

そこでJVMというプラットフォームに向けた書きやすいプログラミング言語が色々と作られていてClojure,Groovy,Scalaなどがそうです、そしてそれらの総称としてAltJavaと呼んでます。

KotlinもいわゆるAltJavaですが、後発なだけあって他の言語よりいくつか優位性があります。
KotlinはJava並の高速なコンパイルとC#やGroovyやScalaのいいとこ取りをしつつシンプルな言語仕様でJavaとの互換性を重視しています。

キーワードもJavaとだいたい同じなのでわかりやすいのではないかなと思います。

他にも言語レベルでのNullSafeな仕様やSmartCastも魅力の一つです。

# Kotlinをどこで使うのか
KotlinはJVM上であればどこでも動かせます。
なのでデスクトップアプリも作れるしサーバーサイドアプリケーションも作れます。
しかもKotlin自体をJavaScriptへ変換することまでできるのでウェブブラウザでも動かせます。
そして僕が注目しているのはやっぱりAndroidアプリの開発です。
言語の見た目がSwiftに似ているのも面白いところで
Swiftを書けるiOSエンジニアがAndroid開発をやることでもできるし
AndroidエンジニアがiOSを開発するのもJava->ObjCという流れよりかは敷居が低くていいのではないかと思います。
Kotlinも既に実務でも使われだしていてノウハウも溜まってきているようです。

さて、ざっくりとですがKotlinでAndroidアプリ開発をするメリットは

- ラムダ式などでコールバックを短くできる
- 拡張関数で自然な文法でコードを書ける
- 結構NullなことがあるのでNullSafeで安心してコードを書ける

などがあります。

# Kotlinを学ぶには

IntelliJ 15 をインストールすれば　デフォルトで入ってるのですぐに書いてみることが可能です。

一番は[公式ドキュメント](https://kotlinlang.org/docs/tutorials/getting-started.html)を見るのがいいのですが
「英語は目に染みるぜー」って方は@ngsw_taroさんが書いてる[解説サイト](https://sites.google.com/site/tarokotlin/)を読んでみるといいと思います。

開発環境用意するのめんどくせーという人でもブラウザで動作する[try kotlin](http://try.kotlinlang.org/)があります。
[問題形式で学べるプログラム](http://try.kotlinlang.org/#/Kotlin%20Koans/Introduction/Hello,%20world!/Task.kt)もあるのでぜひぜひやってください！


# Kotlinの言語的なこと

ここではKotlinの言語的なことをざっくりと語っていきます。

## [NullSafe](https://kotlinlang.org/docs/reference/null-safety.html)

KotlinのNullチェックはBuild時に行います。
なので実行時のオーバーヘッドは０です。

以下のコードはビルドエラーになります。

```kotlin
var name: String = null // Build error
```

コンパイラーが判定できる範囲ではnullの代入をビルドエラーになるのでNullPointerで死ぬまでわからないということは防げるのではないかと思います。

Nullを許容する場合はNullable型を定義します

KotlinでのNullable型の定義方法は型に？を付けてあげるだけです。

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

そしてNullable型のメソッドを呼び出すときは`?.`で呼び出します

```kotlin
var bigName = name?.toUpperCase()
```

nameに文字が入っていればtoUpperCaseは実行されて大文字の名前がbigNameに入りますしnameがNullであればbigNameはNullになります。

ちなみにkotlinは型予測してくれるのでJavaの様にわざわざ型を書かなくてすみます。

この場合のbigNameの型はStringのNullable型になります。

Nullableのメソッドの呼び出しの時に`?`を付け忘れてもビルドエラーになるので安心です。

そもそもIDEを使っていれば警告を出してくれるのでビルドするまでもありませんね。

## [SmartCast](https://kotlinlang.org/docs/reference/typecasts.html)

SmartCastはビルド時にスコープ内で絶対この型という保証があるときチェックした型として利用できる機能です。

例えばJavaだと

```java:java
try {
  ...
} catch (Exception e) {
  if (e instanceof APIException) {
    APIException apiException = (APIException) e;
    System.out.println("Status: " + apiException.getStatus());
  }
}
```

と言った形で書かなくてはならないのをKotlinなら

```kotlin:kotlin
try {
  ...
} catch (e: Exception) {
  if (e is APIException) {
    System.out.println("Status: " + e.status)
  }
}
```

という形で書けます。getStatusはAPIExceptionに定義されているメソッドですが明示的にキャストをせずに使えます。
ifでe変数はAPIExceptionであることを示しているおかげです。

他にもNullable型を`!!.`でメソッドを呼び出した後は確実にそのNullではないので以降はNonNullable型として扱えます。

コード的には以下のようになります。

```kotlin
var name: String? = fetchUserName()
var bigName = name!!.toUpperCase()
var chars = name.split("") // ここはString型として扱える
```

`!!.`は「Nullでないことをこの俺が保証する！！」って時に使いましょう

## [Delegated Properties](https://kotlinlang.org/docs/reference/delegated-properties.html)

デリゲートプロパティはそのプロパティを使うときに処理を挟むことができます。

宣言方法は`by`キーワードを使います

```kotlin
class Example {
  var p: String by Delegate()
}
```

Delegateは以下の様に定義されています

```kotlin
class Delegate {
  operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
    return "$thisRef 、${property.name}を私に任せてくれてありがとう！"
  }
 
  operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
    println("$thisRef の ${property.name}に $value が割り当てられたよ")
  }
}
```

値を参照するときに`getValue`が呼ばれ、値をセットするときに`setValue`が呼ばれます。

```kotlin
val e = Example()
println(e.p)
e.p = "hogehoge"
```

これを活用したAndroidのライブラリで有名なのがKotterKnifeというものがあります。

[JakeWharton/kotterknife](https://github.com/JakeWharton/kotterknife)

これはJava版のButterKnifeでやっているInjectionではなくDelegateでViewの取得をしています。

１ファイルでできているのでDelegateと拡張関数の参考に是非コードをみてみるのをおすすめします。

## [Destructuring Declarations](https://kotlinlang.org/docs/reference/multi-declarations.html)

日本語で言うなら分解宣言でしょうか
何ができるのかというと
１つ以上の値を返すことができます。

```kotlin
class Person() {
  fun component1(): String {
    return "koki_cheese"
  }

  fun component2(): Int {
    return 21
  }
}

person = Person()

val (name, age) = person
```

`component1()`の数値部分を増やしていくことで返せる値をどんどん増やすことができます。

定義方法としてKotlinの`data class`を利用するのが良いと思います。(なんだかGoっぽく書きたくなったので書いてみた)

```kotlin
data class Result<T>(val result: T, val error: Throwable?)

fun timeParse(strDate: String): Result<Date?> {
    val format = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")

    try {
        val date = format.parse(strDate)
        return Result(date, null)
    } catch (e: Exception) {
        return Result(null, e)
    }
}

fun main(args: Array<String>) {
    var (date, err) = timeParse("2015-12-25 00:00:00")
    if (err != null) {
        System.out.println("err: ${err.message}")
        return
    }

    System.out.println("date: ${date!!.time}")
}
```


# まとめ

Javaの資産を使えると言っても　物によっては上手くいかないやつとかもあるので
特にAnnotation Processor系はうまくいく奴と行かない奴もあったりしますkaptを使ってもうまくいかないやつもあるのでそういうところでハマる可能性はあります。

最初は名前が可愛いというだけで手を出しましたが
使えるプログラミング言語でした。
Kotlin自体はとてもシンプルで覚える概念も少ないですし
IDEベンダーが作っているので開発環境の充実ぶりは流石です。

新規のプロジェクトをKotlinでやってみるのもいいし　既存プロジェクトの一部をKotlinにしてみるところからでもはじめて見るのはどうでしょうか？