Kotlinの"きほん"の"き"

KotlinはJetBrains社が開発した汎用プログラミング言語です.
基本的にはJVMで動く言語ですが,JavaScriptへのトランスパイルやネイティブコンパイルもサポートしています.

Javaとの違い

KotlinはJVM上で動くためJavaと比較します.
まず,第一に違うことはnull安全性です.Kotlinはnull許容型があり,nullを入れれる型と入れれない型を明確に区別しています.最近の言語の流行りですね,すごく使いやすいです.null非許容の型にnullを入れるとコンパイルエラーになりますし,null許容型をnullチェック無しで使うとコンパイルエラーになります.安心です.
次のKotlinの違いは演算子のオーバーロードです.Javaでは演算子のオーバーロードは提供されていませんが,Kotlinでは提供されています.そして,面白いことにJavaのメソッドも条件を満たせばKotlinから演算子として使えます.例えばequalsメソッドとかは==演算子として使えます.ちなみにJavaの==はKotlinでは===です.
Javaにもあるような機能なので微妙ですが,古いJavaをお使いの方であればKotlinの型推論は便利だと思います(ダイヤモンド演算子じゃないです).Kotlinは変数宣言の際valvarを使い変数を宣言します.基本的にはvalを一番良く使います.そして,この2つは型を明示的に指定しない場合は自動的に型推論をしてくれます.便利です.

まだまだ,いろいろ違いはありますが,長くなりそうなのでここで一旦切ります.

環境

Kotlinの環境は同じくJetBrains社が開発しているIntelliJ IDEAが最強に相性が良いです.
AndroidはAndroid StudioがIntelliJ IDEAをベースにしているのでAndroid Studioでも同等の機能が使えます.

関数

Javaは全てのメソッドが何らかのクラスに属している必要がありました.しかし,Kotlinはその制約がありません.そしてmain関数もクラス内ではなく外に書きます.
とりあえず,Hello, Worldから始めます.

fun main() {  
    println("Hello, World!")  
}

これがKotlinのHello, World!と表示するコードです.
ひとつひとつ見ていきましょう.
まず,関数を作るときはfunと書きます.そしてその後ろに関数名を書き丸括弧に入った引数リストが続きます.そして,関数本体を記述します.
そして,Kotlinはセミコロンを書かなくても良い言語ですので,一行に複数の文を書かなければセミコロンは省略できます.

足し算をする関数

fun add(n1: Int, n2: Int): Int {  
    return n1 + n2  
}

上記が2つの引数を取り足した値を返す関数です.
引数リストを見てみましょう.引数リストの変数は変数名: 型と書いてあります.Kotlinは変数の宣言は基本的にこの形式で書きますので覚えておきましょう.
関数の返り値の型を見ると: Intになっています.つまりInt型の値を返す関数ということになります.
ちなみに,voidに相当する型はUnitです.

クラス

クラスの作り方はJavaに似ています.

class Klass {
}

最小のクラスは上記の感じになります.

コンストラクタ

コンストラクタはクラスを構築するときに呼び出されるメソッドです.
Kotlinはプライマリコンストラクタとセカンダリコンストラクタがあります.

プライマリコンストラクタ

class Person(name: String, age: Int) {  
}

プライマリコンストラクタの引数はこのようにクラス名の後に記述します.
本体の記述が必要な場合は次のように記述します.

class Person(name: String, age: Int) {  
    val name: String  
    val age: Int  
      
    init {  
        this.name = name  
        this.age = age  
    }  
}

このコードはもっと簡略化できます.

class Person(name: String, age: Int) {  
    val name: String = name  
    val age: Int = age  
}

フィールドの型も省略できます.

class Person(name: String, age: Int) {  
    val name = name  
    val age = age  
}

そもそも,引数とフィールドが同名ですからフィールドの定義と引数の宣言を同時にできます

class Person(val name: String, val age: Int)

このようにKotlinではだいぶ簡潔に記述することができます.

セカンダリコンストラクタ

class Person(val name: String, val age: Int) {  
    constructor() : this("", 30)  
}

セカンダリコンストラクタはconstructor() : this("", 30)の部分です.
この例のようにセカンダリコンストラクタは間接的にでも必ずプライマリコンストラクタを呼び出さなければなりません.

プロパティ

プロパティはフィールドのように呼び出せるメソッドです.Javaから見ると本当にメソッドになってます.
先程の例を使って見てみましょう.

class Person(val name: String, val age: Int)

ここにはnameageというプロパティが定義されています.valとなっていますが,これはプロパティです.Kotlinではクラス内にフィールドを宣言することはできず,今までフィールドと思っていたものはプロパティです.varで宣言するとゲッターとセッターが自動で作成されます.nameだとgetNamesetNameが自動で作られます.valで宣言するとゲッターだけが自動で作成されます.nameだとgetNameだけですね.

プロパティは自分で作ることができます.

class Person(var name: String, val age: Int) {  
    val nameAge get() = name + " " + age  
}

この例ではnameageを合わせて文字列として返すnameAgeというプロパティが作られています(微妙な例ですが).

条件分岐

if式

このタイトルで「ん?」と思いましたか?
Javaではifはでしたが,Kotlinではです.
どういうことかというと

String str = "";
if (flag) {
    str = "flag true";
} else {
    str = "flag false";
}

というJavaコードをKotlinでは

val str = if(flag) { "flag true" } else { "flag_false" }

と書けます.
つまり,if自体が値を持ちます.この機能によりKotlinはほとんどの場面でvarが不要になります.

when式

whenはパターンマッチングを行う機能です.

val value = 30  
when(value) {  
    20 -> println("10")  
    in 0..10 -> println("0..10")  
    else -> println("else")  
}  
  
when {  
    value == 20 -> println("value == 20")  
    value in 0..10 -> println("value in 0..10")  
    value < 50 -> println("value < 50")  
    else -> println("else")  
}

このようなコードが書けます.
もちろん式ですのでwhenも値を持ちます.

ラムダ式と高階関数

ラムダ式

ラムダ式は無名関数と呼ばれます.コールバック関数や後述する高階関数と一緒に使用すると書きやすくなります.

val add = {x: Int, y: Int -> x + y}  
println(add(1, 2)) // 3

このように波括弧で記述し引数を取る場合は->より前で記述します.

高階関数

高階関数は関数を引数に取るか,関数を返す関数のことを言います.よく使われる高階関数としてmapfilterfoldなどがあげられます.

(1..10).filter { it % 2 == 0}.map { it * 2 }.fold("", { acc, i -> "$acc $i" }) // 4 8 12 16 20

このようにまとめて記述することができます.
ifforを使いfiltermapを記述するとやっていることの意味とは関係ない記述が多くなってしまいますが,これらの関数を使うことによって何をしているかが明確になり,わかりやすいコードになります.また,途中経過で値を書き換えるコードが入らないため(入れることはできますが)副作用のないコードとなりバグを生みにくくなります.

おわりに

Kotlinの機能はこれだけではありませんが,とりあえずここで一旦終わりにします

参考文献

コメント

このブログの人気の投稿

C++11の機能 (関数のdefault・delete宣言, overrideとfinal指定子, 移譲コンストラクタ, 継承コンストラクタ)

[C++] 並行・並列処理に関連する標準ライブラリまとめ