ドワンゴで就業形インターンをしているコキチーズです。
主に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 // Build error
コンパイラーが判定できる範囲ではnullの代入をビルドエラーになるのでNullPointerで死ぬまでわからないということは防げるのではないかと思います。
Nullを許容する場合はNullable型を定義します
KotlinでのNullable型の定義方法は型に?を付けてあげるだけです。
var name: String? = null
そしてNullable型のメソッドを呼び出すときは?.
で呼び出します
var bigName = name?.toUpperCase()
nameに文字が入っていればtoUpperCaseは実行されて大文字の名前がbigNameに入りますしnameがNullであればbigNameはNullになります。
ちなみにkotlinは型予測してくれるのでJavaの様にわざわざ型を書かなくてすみます。
この場合のbigNameの型はStringのNullable型になります。
Nullableのメソッドの呼び出しの時に?
を付け忘れてもビルドエラーになるので安心です。
そもそもIDEを使っていれば警告を出してくれるのでビルドするまでもありませんね。
SmartCast
SmartCastはビルド時にスコープ内で絶対この型という保証があるときチェックした型として利用できる機能です。
例えばJavaだと
try {
...
} catch (Exception e) {
if (e instanceof APIException) {
APIException apiException = (APIException) e;
System.out.println("Status: " + apiException.getStatus());
}
}
と言った形で書かなくてはならないのを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というものがあります。
これは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 Processor系はうまくいく奴と行かない奴もあったりしますkaptを使ってもうまくいかないやつもあるのでそういうところでハマる可能性はあります。
最初は名前が可愛いというだけで手を出しましたが
使えるプログラミング言語でした。
Kotlin自体はとてもシンプルで覚える概念も少ないですし
IDEベンダーが作っているので開発環境の充実ぶりは流石です。
新規のプロジェクトをKotlinでやってみるのもいいし 既存プロジェクトの一部をKotlinにしてみるところからでもはじめて見るのはどうでしょうか?