Kotlin概要
Kotlinとは
Kotlin(コトリン)は、IntelliJ IDEAなどのIDE(Integrated Development Environment: 統合開発環境)で有名なJetBrainsを中心に開発が進められている新しいプログラミング言語である。2011年夏に発表され、現在はApache 2.0ライセンスのOSS(Open Source Software)として開発環境とソースコードが公開されており、無料で利用できる。
Kotlinで書かれたコードは、JVM(Java Virtual Machine: Java仮想マシン)上で実行されるJavaバイトコード(おなじみのclassファイル)にコンパイルされる。このようなプログラミング言語をJVM言語という。ScalaやGroovyもKotlinと同じくJVM言語の1つである。また、JavaScriptへのコンパイルもサポートしているため、altJSの1つでもある。Androidアプリ開発もサポートする。
Kotlinは型推論、ラムダ式、トレイトなどの現代的な文法と機能を持つ、静的型付けの本格的なオブジェクト指向言語である。Javaより簡潔で安全なコードを書けることが特徴である。
2016年2月にv1.0がリリースされ、2017年5月のGoogle I/OでGoogleはKotlinをAndroidの公式言語として発表した。Spring Frameworkも2016年にSpringブログでDeveloping Spring Boot applications with Kotlinを公開し、2017年1月にはSpring Framework 5.0でKotlinをサポートすると紹介した。
ちなみにJetBrainsはロシアとチェコ出身の開発者で構成されており、Kotlinはロシアにある島の名前である。開発チームの多くがいたロシアのサンクトペテルブルク近郊の「コトリン」島にちなんで名付けられたという。
なぜKotlinを使うべきなのか
世の中にはすでに数えきれないほど多くのプログラミング言語が存在する。その中で、なぜKotlinなのかを見ていこう。
まず言えるのは、KotlinがJVM言語であるという点である。Javaは世界中で使われている非常に人気のある言語である。1995年に登場して以来、多くのコードが書かれ、多くのシステムが運用されてきた。Javaは今も進化を続けている。しかしその一方で、後方互換性(backward compatibility)を維持するため、技術の重複や型安全性の問題は改善しにくい面がある。そこでJVM言語が登場した。Javaが抱える問題から解放されてプログラミングできるだけでなく、高い信頼性と性能を持つJVM上で動作し、Javaで書かれた既存のライブラリやフレームワークなどの資産を活用できる利点もある。
JVM言語だけでも数は非常に多い。有名なものにはScalaやGroovyがあり、この競争の中でJetBrainsはKotlinの設計目標を次のように定めている。
- Java互換
- 少なくともJavaと同等のコンパイル速度
- Javaより高い安全性: nullポインター逆参照(dereference)のようなよくあるミスに対する静的チェックなど
- Javaより高い簡潔性: 型変数の推論、高階関数(クロージャ)、拡張関数、ミックスイン(mixin)、ファーストクラスデリゲーションなどをサポート
- Scalaより簡単な方法で表現力を実用的な水準に保つ
特徴的なのは、nullポインター逆参照、つまりNullPointerExceptionが起こらないような仕組み(Null Safe)が言語機能として提供されている点である。そのほかにもミスを未然に防ぐ機能があり、Javaよりも発生しがちなバグを起こしにくい言語になっている。安全に重きを置くとコードが複雑になるのではないかという心配があるかもしれないが、その点もKotlinでは考慮されている。こうした特徴に加えて、Javaに似た文法で学習コストが低いため、実務での利用に適していると考えられる。
Kotlinの特徴
簡潔、安全、JavaバイトコードとJavaScriptにコンパイル可能、静的型付け、オブジェクト指向、クロージャなどは、Kotlinを説明する決まり文句にすぎない。しかし、どれもKotlinの特徴を端的に表す重要な言葉である。簡単なコードを交えながら1つずつ紹介する。
簡潔である
行末のセミコロン不要、型推論、データクラス、拡張関数など。
Kotlinコード自体の単純さはもちろん、文法、つまり書き方のルールも簡潔である。コードが簡潔なため、タイピング回数が減り、エラーが発生しにくいだけでなく、可読性が高くなり保守コストの削減も期待できる。また文法が簡潔なため学習コストが低く、プログラマーのレベル差によるコードのばらつきを減らすことができる。次の例1は、いつものHelloWorldをKotlinで書いたコードである。
例1 KotlinでHelloWorld
package sample
fun main(args: Array<String>) {
val message = "Hello, world!"
println(message)
}
CLIの黒い画面に挨拶が表示されるだけの簡単なプログラムだが、Kotlinの特徴を見ることができる。まず、トップレベルで関数を定義できることが分かる。funキーワードは関数定義に必要なキーワードである。そしてmainという名前で、Array<String>型の引数を含む関数がKotlinプログラムのエントリーポイントである。変数の型が変数名の後ろに来る点もJavaとは異なる。
表示するメッセージを変数messageに代入する。Kotlinではvalキーワード(またはvar)を使用して変数を宣言する。messageはString型だが、右辺から推論できるため明示する必要はない。
printlnは引数の値を標準出力へ出力する関数である。セミコロン(;)を文末に明示する必要はない。同じ行に続けて文を書く場合は;で区切る必要がある。
さらに簡略化して次のように書くこともできる。
例2 より簡潔になったHelloWorld
package sample
fun main() {
println("Hello, world!")
}
安全である
Null safe: 変数や関数の戻り値などにnilが入る可能性があるかを明示する必要がある。
前述したように、KotlinはJavaに比べて安全である。型やnullの扱いが厳格である。たとえばKotlinでは、キャストやnull逆参照によるランタイム例外が発生することは非常にまれである。
Kotlinはnullを代入できる変数とできない変数を区別する。次の例3では、bにnullを代入する箇所でコンパイルエラーが発生する。通常の型(ここではString)の変数にはnullを代入できない。
例3 通常型の変数にはnullを代入できない。
val a: String = "Kotlin" // OK
val b: String = null // NG!!
少し変更した例4はコンパイルに成功する。変数cとdの型がString?になっている。
例4 ?が付いた型の変数にはnullを代入できる。
val c: String? = "Kotlin" // OK
val d: String? = null // OK
このように?が後ろに付く型の変数にはnullを代入できる。しかし、変数が参照するオブジェクトのメンバーへのアクセスには制限がある。これはNullPointerExceptionを防ぎ、Null安全を実現するためである。Null安全については次回以降に改めて説明する。
JavaバイトコードとJavaScriptにコンパイルできる
すでに紹介したように、KotlinはJVM言語であり、コンパイラーはJavaバイトコードにコンパイルする。KotlinコードからJavaコードを呼び出せるだけでなく、JavaコードからKotlinコードを呼び出すこともできる。例5は、Java標準ライブラリをKotlinコードから呼び出してテキストファイルの内容を表示する例である。
例5 KotlinでJava標準ライブラリを使用する
import java.nio.file.Files
import java.nio.file.Paths
fun main(args: Array<String>) {
val path = Paths.get("/memo.txt")
val lines = Files.readAllLines(path)
for (line in lines) {
println(line)
}
}
また、コンパイラーはKotlinコードを入力としてJavaScriptコードへ変換することもできるため、望むならバックエンドとフロントエンドの両方をKotlinで開発できる。
静的型付け(Static typing)言語である
Kotlinはコンパイル言語である。これは単にインタープリター言語より実行速度が速いということだけを意味しない。コンパイラーはコンパイル時にソースコードのエラーを発見し、実行コードを生成しないため、プログラマーは早期にバグを発見して安全なプログラムを作れるようになる。
静的型付け(Static typing)プログラミング言語とは、変数が使用前に定義されている必要があるプログラミング言語をいう。
オブジェクト指向言語である
Kotlinはクラスベースのオブジェクト指向言語である。Javaと同じように、定義されたクラスからインスタンスを生成できる。例6はクラスを定義してインスタンスを生成する簡単な例である。すでにオブジェクト指向言語を知っている人には、親しみやすい文法だと感じるだろう。
例5 Userクラスのインスタンス生成と使用
// Userクラス定義
class User {
// プロパティ
var id: Long = 0
var name: String = ""
// メソッドオーバーライド
override fun toString(): String {
return "name=" + name
}
}
fun main(args: Array<String>) {
// Userインスタンス生成
// newキーワードの記述は不要
val user = User()
user.id = 12345
user.name = "devkuma"
println(user.toString()) // => name=devkuma
}
KotlinにはJavaと異なり基本型(Primitive type)がなく、すべてがオブジェクトである。また、プロパティやトレイト(trait)、オブジェクト宣言など、Javaにはない便利な機能が提供されている。
クロージャ(Closure)
Kotlinにはファーストクラスオブジェクトとしての関数がある。つまり、関数を他の値と同じように関数の引数として渡したり、戻り値として受け取ったりできる。これにより、より細かい単位で関数を再利用でき、抽象的なプログラミングが可能になる。これがKotlinを簡潔にする方法の1つである。
Kotlinの標準ライブラリが提供するCollection Operations APIの例である例7を見てみよう。
例7 関数を引数として渡してリストを操作する
// 操作対象のリストを作成
val list = listOf(3, 5, 2, 7, 4)
println(list) // => [3, 5, 2, 7, 4]
// 各要素を2倍したリストを作成
val twice = list.map { e -> e * 2 }
println(twice) // => [6, 10, 4, 14, 8]
// 偶数の要素だけにフィルタリングしたリストを作成
val even = list.filter { e -> e % 2 == 0 }
println(even) // => [2, 4]
このような関数はクロージャ(Closure)と呼ばれる。クロージャは内部で参照する外部の変数をキャプチャする関数である。コードを見ながら説明する方が理解しやすいため、クロージャの詳しい説明は次回にする。
まとめ
今回はKotlinの紹介として、概要と特徴、簡単な文法を扱った。KotlinはJetBrainsから始まったオープンソースのJVM言語である。その機能と文法は簡潔さと安全性を兼ね備えている。オブジェクト指向、クロージャ、型安全など、現代的な言語に欲しい機能をひと通り備えている。特にNull安全は独自のメカニズムである。
次回は開発環境を準備し、プログラミングの例で実習する。
付録: Kotlinの学習方法
Kotlinを学習する方法はいくつもあるが、自分に合った方法を見つけることが重要である。書籍を好む人もいれば、インターネットサイトやブログを探して読むのが好きな人もいるだろう。また、動画講座を見たい人もいるはずである。
-
公式ドキュメント
-
Kotlin動画講座
個人的には、いくつかの方法を試してみることをおすすめしたい。簡単な動画講座から始め、インターネットページを読み、書籍で詳しく確認しながら言語に親しんでほしい。これはKotlin学習だけに限ったことではないだろう。どんな学問でも、まず小さな木を見て、少しずつ範囲を広げて森全体を見られるようになる。