• 66
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

ドワンゴで就業形インターンをしているコキチーズです。
主に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 をインストールすれば デフォルトで入ってるのですぐに書いてみることが可能です。

一番は公式ドキュメントを見るのがいいのですが
「英語は目に染みるぜー」って方は@ngsw_taroさんが書いてる解説サイトを読んでみるといいと思います。

開発環境用意するのめんどくせーという人でもブラウザで動作するtry kotlinがあります。
問題形式で学べるプログラムもあるのでぜひぜひやってください!

Kotlinの言語的なこと

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

NullSafe

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

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

var name: String = null

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

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

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

var name: String? = null // Build error

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

var bigName = name?.toUpperCase()

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

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

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

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

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

SmartCast

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

例えばJavaだと

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

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

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

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

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

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

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

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

Delegated Properties

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

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

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

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

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が呼ばれます。

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

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

JakeWharton/kotterknife

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

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

Destructuring Declarations

日本語で言うなら非構造体宣言でいいのでしょうか
何ができるのかというと
1つ以上の値を返すことができます。

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

  fun component2(): Int {
    return 21
  }
}

person = Person()

val (name, age) = person

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

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

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 Processer系はうまくいく奴と行かない奴もあったりしますkaptを使ってもうまくいかないやつもあるのでそういうところでハマる可能性はあります。

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

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

この投稿は ドワンゴ Advent Calendar 20152日目の記事です。