Kotlinとは、プログラミング言語の一つである。
概要
KotlinとはJava仮想マシン上で動作するプログラムを制作できるプログラミング言語である。いわゆるJVM言語であるが、どちらかというとAndroidアプリ開発に重きが置かれている。バージョン1.1(2017年3月1日リリース)からはJavascriptへのトランスパイルも公式にサポートするようになった。
開発元はIntelliJ Ideaなどの各種言語の統合開発環境の開発会社として知られるJetBrains社。
2016年2月17日にバージョン1.0がリリースされた。2012年2月14日からオープンソース化されている。
Java(とJava仮想マシン)のリリースサイクルが半年ごとに変更された影響か、2021年のバージョン1.5から半年ごとのローリングリリース方式になった。
命名の由来
JetBrains社はチェコ共和国に本社を置く企業だが、開発拠点をロシアのサンクトペテルブルクにも有している。Kotlinはその拠点で開発されたので、サンクトペテルブルクの近くにあるKotlin島にちなんで命名された。
"kotlin"自体はフィンランド語で「やかん」のこと[1][2]であり、日本語の愛称っぽく聞こえるのはただの偶然である。
特徴
長所
JavaやScalaの反省を活かした言語仕様
デフォルトでnullの回避を強制できる言語仕様が最大の特徴だが、nullの回避方法などの文法がSwiftとかぶるとか言われたりする。
静的型付けJVM言語である点がScalaとかぶるが、言語仕様が複雑になり過ぎないように「実用性を重視してバランスをとった」という点で差別化されており、JavaだけでなくScalaでの反省も踏まえた後発言語ならではの設計になっている。
他のJVM言語同様、Javaのライブラリはシームレスに相互利用できる。記号だけのメソッド名がない分、ScalaよりもJavaからの呼び出しがやりやすい。
統合開発環境が使える
Kotlinレベルのマイナー言語では開発環境はテキストエディタとコマンドラインのみということも珍しくないが、JetBrains社が開発している言語だけに、同社が開発しているAndroid StudioやIntelliJ IDEAでサポートされている。
短所
Android開発に引きずられた仕様
Android開発(Java6ベース)を念頭に置いてきた経緯があるため、標準ライブラリではAPIがJava6ベースになっているところがある。たとえばPathやjava.timeのようなJava7以降に入ってきたものはkotlin標準ライブラリでは使われていない。Android開発環境はJava7に対応したのも遅かった(2014年)し、Java8対応が始まったのはKotlinバージョン1.0のリリースよりも後なので仕方のないことかもしれない。
Java8のライブラリを普通に使用できるのでそれほど問題ないとはいえ、今後もAndroid開発への対応が足を引っ張ることはあるかもしれない。
Javascriptへのトランスパイルやネイティブコードへのコンパイルもサポートする方針とのことだが、この仕様が足をひっぱったり、さらにはいつの間にかなくなっていたり(Scalaは初期に.Netへのコンパイルもサポートしていたが、いつの間にかなくなった)するかもしれない。
他のIDEは事実上選べない
JetBrains社謹製のEclipseプラグインもあるが、2017年現在アルファ版で実用には耐えない。おまけにAndroid公式言語採用が決まった2017年半ばからはほぼ開発が止まっている。まるでGoogleに採用してもらうアピールのために開発をしていたから用済みになったかのようだ。Android StudioやIntelliJ IDEAを手がけるJetBrains社が、競合製品であるEclipseに塩を送るわけにはいかないことを考えると、IDEの垣根を越えて普及できるのか疑問に残るところはある。
用途
Javaが "write onece, run anywhere" で象徴されるような、同じコードで全ての環境に対応に対応可能という方針をとっているのに対し、Kotlinは"(コードをそのまま使うことは出来ないが)Kotlinの文法さえ知っていれば、どの分野でも対応したコードが作成可能"といったレベルを目指しているようだ(Kotlin1.2のリリースあたりからその方針が特に明確になった)。
Android開発
Android開発の標準IDEであるAndroid Studioでサポートされている。最もサポートが手厚く、成功しているといえる分野。2017年5月17日、Android OSの開発元であるGoogleもKotlinをAndroidの公式開発言語の一つとして採用すると発表した(Javaの採用を廃止したわけではない)。
2019年5月7日にはGoogleがKotlinをAndroidの推奨開発言語に格上げした。
Kotlin/JVM
traitのようなJavaにない概念があるScalaと異なり、単一継承であるclassと、実装を持たないことがある抽象クラス、interfaceという切り分け方はJavaと同じである(ベータ時代にはtraitがあったが、正式版になる前に廃止された)。
また、メソッド名への記号使用を原則禁止しているためScalaのような記号演算子をJava側でどう対応させるかという問題もほとんど生じない。
こういったことにより、JavaとKotlinはクラス・インターフェイスやメソッドが一対一に対応しており、両者を混在させて開発することすら可能となっている。
また、Android StudioやIntelliJ IDEAにはJavaのコードをKotlinのコードに変換する機能がある(ただし、nullの扱いが悪いとなかなか手直しなしでは動かないらしい)。
Kotlin script
.ktが標準の拡張子だが、.ktsという拡張子にしてスクリプトとして実行することも可能である。
Gradle
ソースコードを実行ファイルにする過程をビルドというが、JavaのビルドツールでAnt, Mavenについで普及してきたものにGradleがある。
GradleのビルドスクリプトはGroovyという別のJVM言語で記述されてきたのだが、2016年8月からGroovy以外にKotlinスクリプトで記述することも可能になった。
初期にはIDEなどの支援がなかったため、Kotlinでビルドスクリプト書かれることはほとんどなかったが、2018年11月26日リリースのGradle 5.0からはKotlin DSLが実験的扱いから正式にバージョン1.0となり、使用例も増えつつある。
Kotlin/JS
前述のようにJavascriptにトランスパイルすることができるので、Webアプリ開発に用いることもバージョン1.1以降は視野に入ってくると思われる。
ただ、この分野ではTypescriptに大きく水をあけられており、いらない子になる可能性も否定できない。
Kotlin/Native
バイトコードでもJavascriptでもなく、Java仮想マシンなしでも動くネイティブコード(通常のバイナリ)を生成するプロジェクト。コンパイルにはLLVMを用いている。
JVM用のKotlinのコードをJava仮想マシンなしで動かすことは目標としておらず、Javaのライブラリも使えない。
主なターゲットはiOSアプリ開発らしい。これが実現すればJVMが動くデスクトップOSWindows, Mac, Linuxに加え、モバイルOSのAndroid, iOS、さらにはJavascriptトランスパイルによるWebブラウザ上での動作と、ほぼ全てのプラットフォームをカバーすることになる。
2017年5月12日にバージョン0.2が出た後もバージョンアップを重ねていたが、Kotlin本体のバージョンが1.3になったのに伴い、Kotlin/Nativeのバージョンも1.3に引き上げられた。しかし製品開発に耐えるとされるProduction Readyの表示は2019年10月の段階でもまだなされていないようである。
Webフレームワーク
Spring: Javaで実績のあるフレームワークだが、Kotlinもサポートするようになった。
Ktor: Kotlin公式プロジェクトではないが、Kotlin開発元のJetBrains社公式プロジェクト。廃れてしまったWasabiやKaraといったフレームワークに代わってサーバーサイドプログラミングを目指しているらしい。
サンプルコード
Hello World
fun main() = println("Hello, World!")
FizzBuzz
パズルゲームのソルバ
「ロボットにこころを」というパズルゲームの解法探索プログラム → こちら(ネタバレ注意)
Kotlin/JS
ニコニコ大百科:グラフ機能にはKotlin/JSを用いている → バージョン1.0のソースコードはこちら
関連動画
関連商品
右上の本はKotlinの言語開発のメンバーが著者(なので「プログラミング言語Kotlin」的な位置づけ)らしい。
外部リンク
関連項目
- Java / Java仮想マシン / JVM言語
- NullPointerException
- Android
- Javascript / トランスパイル
- ローリングリリース
- プログラミング言語
- プログラミング関連用語の一覧
細かい長所と短所
静的型付けJVM言語ということでJavaやScalaとの比較になるが、細かい特色を挙げていく。「〜できない」という点は便宜上短所に分類した場合が多いが、見方次第で長所にも短所にもなるのはどの言語でもいえることである。
Kotlin独自のもの
長所 | 短所 |
---|---|
デフォルトでnull安全。 | ただし、Javaから持ち込まれたクラス・メソッドについてはnull安全の保証なし。 |
継承に頼らないdelegateを文法でサポート。 | クラスやメソッドはデフォルトでは継承不可。 |
クラスの外(トップレベル)で関数定義が可能。main()もトップレベル関数。 | thisを省略すると、トップレベル関数なのかメソッドなのか、見ただけではわかりにくい。 |
拡張関数で、クラスにメソッドが追加されたかのように扱うことが可能。 | 拡張関数は演算子のオーバーロードには使えない。 また、クラスのAPIドキュメントを読んでもクラス外に定義された拡張関数の情報は見落とすおそれあり。 |
拡張関数により柔軟なDSL構築と、そのDSLによる構造化された記述が可能。 | DSLのネストが深くなると、省略したthisが意図しないレベルのthisを指していても気づけない。 |
関数リテラルの書き方にラムダ式と無名関数の2種類があり、returnの挙動などが同一ではないため、使い分けることを強いられているんだ! | |
並列処理はスレッドより軽量なコルーチンが使える。 | kotlinx.coroutinesライブラリが別途必要。 |
Scalaと似ているがやや異なるもの
長所 | 短所 |
---|---|
プリミティブ型はないので、ジェネリクスなどでも全てオブジェクトとして統一的に扱える。 | Javaのプリミティブ配列のために専用のクラスがある。 |
反復処理できるものに、ArrayとListとSequenceとRangeがあり、お互いは継承関係にないため、せっかくintとIntegerの区別がなくなったのに、関係がより複雑になっている。 | |
高階関数による柔軟なプログラミング。 | apply, let, runとか、fold, foldIndexed, foldRight, reduceとか、似たような機能をもつ関数が多数あって紛らわしい。 |
行末のセミコロンは省略可能。Pythonなどのようなインデントや改行の制限もほとんどない。 | その代わり、ラムダ式などに括弧が省略できないところが多い。 |
演算子は四則演算・比較など主だったもののみ定義可能。 不便に見えるが、Scalaのように一見して何に使うかわからない記号メソッドが溢れかえることはない。 |
独自の記号演算子は定義できない。 |
黙示の型変換は行われないので、コードを見ていて型が分からなくなることは少ない。 | BigIntegerやBigDecimalのリテラルがない上に、黙示の型変換もないので、せっかく演算子は記号で短く表現できても、数値はBigInteger(3)といった冗長な表記をしなければならない。 |
バージョン1.1から型エイリアスが導入された。 | 各自が勝手に型の別名を導入すると、コードを見ていて型が分からなくなるおそれがある。 |
ヒアドキュメント(raw string)方式でエスケープ処理なしで文字列が書ける。それでも、変数の埋め込みが可能。 | ヒアドキュメント方式でも変数埋め込みを許可したため、'$'だけはエスケープ処理が必要という中途半端な仕様になっている。 |
PairやTripleがあり、複数の値を返すことは可能。 | タプルはないので、4つ以上の数の値を返す場合にはdata型を定義することになる。ただし、定義は1行で済ませることもでき、Javaのようにクラスを作るよりは大分手軽である。 |
ブロックの最終行の値を返すreturnが文脈によって必須だったり不要だったりしてややこしい(Javaは一貫して必須、Scalaは一貫して省略可能)。 | |
Scalaのtraitはないが、Java8同様interfaceがデフォルト実装を持てるので、それほど大きな違いはない。 | |
公式でJavascriptへのトランスパイルをサポート(Scala.jsやJSweetは非公式) | APIドキュメントにJVM向けとJavascript向けの情報が混在してカオス。 |
Scalaとかぶるもの
長所 | 短所 |
---|---|
プロパティによりgetterやsetterが不要。 | |
変数の宣言にvar(変更可)とval(変更不可)があり、ListなどのCollectionもデフォルトではイミュータブル。(Scalaと同じ) | Listがイミュータブルなのはいいが、MutableListがListを継承しているために、List型の変数のところにMutableListを代入できてしまう。(Scalaとはやや異なる) |
ちなみに、非JVM言語を含めて主要言語でチェック例外があるのは後にも先にもJavaだけらしい。 | 例外は全て非チェック例外なので、Javaの安全機構をスルーする可能性がある。 |
tailrecをつければ末尾再帰最適化が可能。 | えっ? 最適化ってコンパイラの仕事じゃないの? |
inlineで関数などをインライン展開して最適化が可能。 | えっ? 最適化って(ry |
ちなみに、かつては公式サイト(英語)に「Scalaとの比較」というページがあり「もしScalaで幸せなら、あなたにKotlinは不要である」と書かれていたが、Kotlin 1.1のリリース前後にページごと消えてしまった。
スコープ関数早見表
Kotlinには、関数(メソッド)を引数に取り、オブジェクトにメソッドを適用して、値を返す拡張関数が定義されている。スコープ関数と呼ばれるこれらの関数は、用途によりalso, apply, let, run, use, withと細かく分かれている。区別して覚えられないから一本化してもらえないだろうか。拡張関数型と関数型の継承関係とかを使えばできそうな気がするのだが。
これらの高階関数自体が高階関数の引数になったりとか、これでメソッドを数珠つなぎにして適用したりとか。
戻り値 | 引数に取る関数・メソッド | |
---|---|---|
関数・ラムダ式 | メソッド・拡張関数 | |
オブジェクト自身[3] | T.also() | T.apply() |
オブジェクトに関数(メソッド)を 適用した戻り値[4] |
T.let() T.use()[5] |
T.run() with(T) |
引数をとらない関数の戻り値 | run() | -[6] |
脚注
- *実際島を上空から見るとやかんのような形をしている。
- *Google翻訳によるとフィンランド語で「やかん」は"kattila"となっており、また、「Kotlin島(ロシア領)」がロシア名で、フィンランド語ではKotlin島をレトゥサーリと呼んでいることから考えると、"kotlin"はロシア側の領土になる13世紀より前の古いフィンランド語なのかもしれない。
- *引数に取った関数の戻り値は捨てていることになる。JavaのList.add(戻り値はリストに要素の追加が成功したらtrue、失敗したらfalse)のように、戻り値は利用せずに副作用などを目的とした関数を引数にするのが主な用途ということになる。
- *戻り値がUnit型というのもアリ。
- *Java7のtry-with-resourcesに相当。
- *そもそもオブジェクト自身すら引数にとらないメソッドや拡張関数を定義することはできない。
- 0
- 0pt