Kotlin基礎文法

サンプルコードはKotlin公式リファレンスKotlin公式リファレンス:https://kotlinlang.org/docs/reference/に補足・和訳した物を利用している。

関数

main関数

プログラム全体のエントリポイント(実行開始ポイント)となるのが、main関数である。 拡張子(.kt)のファイルに作成する。

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

関数の作成

エントリポイントの他に、処理の集まりとして関数を作成することができる。

fun 関数名(仮引数:仮引数の型, ・・・): 戻り値の型 {
    関数内の処理
    return 戻り値
}

例えば、仮引数の加算結果を戻り値とする関数は以下の通りとなる。

fun sum(a:Int, b:Int):Int {
    return a + b
}

処理が単文で記述可能な場合、戻り値の型やブロックを省略することができる。

fun sum(a:Int, b:Int) = a + b

戻り値なしの関数の場合、戻り値の型はUnitである。

fun sumPrint(a:Int, b:Int):Unit {
    println("$a と $b の加算の結果は ${a + b}")
}

Unit型は省略が可能である。

fun sumPrint(a:Int, b:Int) {
    println("$a と $b の加算の結果は ${a + b}")
}

変数

再代入不可の変数定義

Kotlinの場合、再代入ができない変数の定義にはvalキーワードを用いる。

val 変数名: データ型 = 初期値
val 変数名 = データ型   // 型推論による代入
val 変数名: データ型    // 変数定義
変数名 = 初期値         // 初期値の代入

例えば、Int型の変数にそれぞれ初期値を代入する方法は以下の通りである。

val a: Int = 1
val b = 2
val c: Int
c = 3

再代入可の変数定義

再代入可能な変数定義には、varキーワードを用いる。 それ以外の利用方法については、valの場合と同じ。

var a: Int = 1
var b = 2
a += 1
b = b + a

Null値の扱い

Kotlinでは、変数や戻り値などにnull値を利用することは基本的にできない。

val s: String = null    // コンパイルエラー

Javaのライブラリを使用する場合など、どうしてもnull値を利用しなければならない場合などは型指定部分に?を付与する。これをnull許容型という。

val s: String? = null

fun returnNullFunc():String? {
    return null
}

fun getNullFunc(s: String?){
    if(s == null) println("引数はnull")
    else println("引数は $s")
}

null許容型へアクセスする場合、変数名の後ろや関数実行後に?を付与する。

val s: String? = null
println(s?.length)
println(s?.toIntOrNull()?.plus(10))

変数にnullが代入されている場合に?でアクセスした結果はnullとなる。

var s: String? = null
println(s?.length)  // 実行結果:「null」と表示
println(s?.length?.plus(10))    // 実行結果:「null」と表示

null許容型へのアクセスで確実にnullではないことが保証される場合、変数名の後ろに!!を付与する。

var s: String? = "Sample"
println(s!!.length)

nullの場合に代入する値を?:で指定することも可能。

val s: String? = null
val len = s?.length ?: -1     // nullの場合は-1が代入される

分岐

プログラム一般で利用されるif - else if - elseと、when(他言語におけるswitchと同等)が利用可能。

if - else if - else

if (条件式1) {
    条件式1がtrueの場合の処理
} else if  (条件式2) {
    条件式1はfalse、条件式2がtrueの場合の処理
} else {
    全条件が全てfalseの場合の処理
}
fun maxOf(a: Int, b: Int): Int {
    if (a > b) {
        return a
    } else {
        return b
    }
}

Kotlinの場合、ifブロックの最終ステートメントは戻り値を表す。

val a = 10
val b = 12
val max = if(a > b){
    println("a > b")
    a   // if の戻り値はa
} else {
    println("a <= b")
    b   // if の戻り値はb
}
println(max)    // 変数bの値「12」がmaxに代入される

処理が単文で記述可能な場合、{}を省略可能。また、戻り値を利用することにより3項演算子のような利用方法も可能。

fun maxOf(a: Int, b: Int) = if (a > b) a else b

Range

in ..を利用することにより、数値などの範囲を指定することが可能。

val a = 5
if (a in 0..5){
    println("0以上5以下の範囲内")
} else {
    println("範囲外")
}

!in ..で範囲外を表すことも可能。

val a = 6
if (a !in 0..5){
    println("0より小さいか5より大きい")
} else {
    println("範囲外")
}

when

when構文は他言語におけるswitchと似たような記述方式となるが、さらに複雑な記述が可能となっている。 ifと同様、ブロックの最終ステートメントが戻り値となる。

when (変数){
    値1 -> {
        処理1    // 変数 == 値1となる場合の処理
    }
    値2 -> 処理2    // 変数 == 値2となる場合の処理
    else -> 条件に当てはまらない場合の処理
}
val x = 2
val message =
    when (x) {
        1 -> "x == 1"
        2 -> "x == 2"
        else -> {
            println("xは1または2ではない")
            "x == $x"
        }
    }
println(message)

whenの場合、比較する値を複数指定することも可能。

val x = 2
val message =
    when (x) {
        1, 2 -> "x == 1 または x == 2"
        else -> {
            print("xは1または2ではない")
            "x == $x"
        }
    }
println(message)

in ..やRange変数などを利用することも可能。また、Boolean型を返すような関数や演算子を利用することも可能。

val validNumbers: IntRange = -10..0     // Range変数

fun checkRange(x: Any) =        // Any型:null許容でない全てのクラスのスーパークラス
    when (x) {
        in 1..10 -> "xは1から10の範囲内"
        in validNumbers -> "xは-10から0の範囲内"
        is Double -> "浮動小数点型"         // is データ型 でデータ型チェックが可能
        else -> "いずれでもない"
    }

ループ

whileとdo - while

Kotlinにおけるwhiledo - while は、Javaなどと同等。

while(条件式){
    ループ処理
}

do {
    ループ処理
} while (条件式)

break、continueも利用可能。

var x = 0
while(x < 10){
    x++
    if (x == 8){
        println("break")
        break
    }
    if (x % 2 == 0) continue
    println(x)
}

break、continueラベル

Kotlinの場合、ネストされたループのbreak先・continue先をラベルにて指定することが可能。 通常のbreakやcontinueの場合、ネストされたループの場合はbreakやcontinueが記述されたループのみが対象となる。

var x = 0
while(x < 3){  // (1)
    x++
    var y = 0
    while (true) {  // (2)
        if (y == 3) break   // (2)のループのみbreakする
        y++
        println("x=$x,y=$y")
    }
}

実行結果

x=1,y=1
x=1,y=2
x=1,y=3
x=2,y=1
x=2,y=2
x=2,y=3
x=3,y=1
x=3,y=2
x=3,y=3

breakやcontinueでラベルを指定することにより、ネストされたループの対象を指定することができる。 ラベル名@でbreakやcontinueの指定先を、break@ラベル名continue@ラベル名でラベルに移動するためのキーワードを指定する。

var x = 0
loop@ while(x < 3){ // break対象「ラベル名@」で指定
    x++
    var y = 0
    while (true) {
        if (y == 3) break@loop  // breakの移動先を「@ラベル名」で指定
        y++
        println("x=$x,y=$y")
    }
}

実行結果

x=1,y=1
x=1,y=2
x=1,y=3

for

Kotlinのfor文は、Pythonのfor文やJavaでいう拡張for文のような利用方法となる。

for (変数 in 範囲を持つ値) {
    ループ処理
}

範囲を持つ値(iteratableな値)とは、以下のルールが必須となる。

一般的にはコレクション型である、またはRange型であれば上記の条件を満たす。

例えば、1から3の間処理を繰り返すようなfor文は以下の通り。

for(i in 1..3){     // [1, 2, 3]の数列からiに要素を代入し、要素が無くなるまでループする
    print("$i ")
}

数値の範囲であれば、downToを利用することにより降順の数列を作ることも可能。

for(i in 3 downTo 1){   // [3, 2, 1]の数列からiに要素を代入し、要素が無くなるまでループする
    print("$i ")
}

また、stepと組み合わせることにより要素の増減値を指定することも可能。

for(i in 1..10 step 2){   // [1, 3, 5, 7, 9]の数列からiに要素を代入し、要素が無くなるまでループする
    print("$i ")
}

untilを利用すると、最後の値を含まないような数列も作成できる。

for(i in 1 until 3){   // [1, 2](3は含まない)の数列からiに要素を代入し、要素が無くなるまでループする
    print("$i ")
}

Collection(リストなど)の場合も同様。ただし、変数に対するデータ型指定はあった方が良い。

val list = listOf<String>("a", "b", "c")
for(s:String in list){
    print("$s ")
}