Edit Page

条件式とループ

if式

Kotlinでは、ifは式であり、すなわち値を返します。従って、三項演算子は存在しません(条件 ? 真の時 : 偽の時)。なぜなら普通の if がその役割を果たすためです。

fun main() { val a = 2 val b = 3 //sampleStart var max = a if (a < b) max = b // else付き if (a > b) { max = a } else { max = b } // 式として max = if (a > b) a else b // `else if`も式の中で使える: val maxLimit = 1 val maxOrLimit = if (maxLimit > a) maxLimit else if (a > b) a else b //sampleEnd println("max は $max") println("maxOrLimit は $maxOrLimit") }

if の分岐はブロックにすることができ、最後の式がそのブロックの値となります:

val max = if (a > b) { 
    print("aを選びます") 
    a 
} else { 
    print("bを選びます") 
    b 
}

もしifを文ではなく式として使用する(例えば値を返したり変数に代入したりする)ならば、その式にはelse分岐が必要です。

when式

when は一つの条件式に複数の分岐を定義します。 C系の言語におけるswitch式に似ています。最も簡単な形式では、次のようになります:

when (x) {
  1 -> print("x == 1")
  2 -> print("x == 2")
  else -> {
    print("x は1でも2でもありません")
  }
}

when はその引数が満たされる分岐が現れるまで、順番に全ての分岐に対して比較されます。

when は式としても文としても使うことができます。 もし式として使用されれば、その値は条件が最初に満たされた分岐の値が式全体の値となります。 もし文として使用されれば、個別の分岐の値は無視されます。 ifと同様に各分岐はブロックでも良く、その場合は値はブロック内の最後の式のものとなります。

else節は他の分岐の条件が全て満たされなかった際に評価されます。

もしwhenとして使用されれば、全てのあり得る場合を分岐条件で網羅できていることをコンパイラが保証出来ない限りは、else節は必須です。 全部の分岐条件を網羅出来ている事をコンパイラが保証出来るケースとしては、 列挙型クラスのエントリやsealedクラスのサブタイプなどが挙げられます。

enum class Bit {
    ZERO, ONE
}

val numericValue = when (getRandomBit()) {
    Bit.ZERO -> 0
    Bit.ONE -> 1
    // 全部のケースをカバー出来ているので 'else' は不要
}

whenでは、以下のケースでは else節は必須です:

  • whenの条件がBooleanenumsealed 型か、そのnullableバージョンの場合(訳注:この文は誤りな気がする、たぶんBooleanの場合だけが正解)
  • whenの分岐が対象のすべてのケースをカバーしていない場合
enum class Color {
    RED, GREEN, BLUE
}

when (getColor()) {  
    Color.RED -> println("red")
    Color.GREEN -> println("green")   
    Color.BLUE -> println("blue")
    // 全部のケースがカバーされているので 'else' は不要
}

when (getColor()) {
    Color.RED -> println("red") // GREENとBLUEについての分岐が無い
    else -> println("not red") // 'else' が必要
}

複数のケースに対して共通の処理をしたい場合は、分岐の条件を一行でカンマでまとめる事が出来ます:

when (x) {
  0, 1 -> print("x == 0 or x == 1")
  else -> print("それ以外")
}

分岐条件として任意の式(定数に限らない)を使用することができます:

when (x) {
  parseInt(s) -> print("sはxをエンコードする")
  else -> print("sはxをエンコードしない")
}

inまたは!inを使用すると、コレクションや 範囲 (range) に入っているかをチェックすることもできます:

when (x) {
  in 1..10 -> print("xは範囲内")
  in validNumbers -> print("xは有効")
  !in 10..20 -> print("xは範囲外")
  else -> print("どれにも該当せず")
}

値をチェックする他の方法として、特定の型のisまたは!isがあります。 スマートキャストのおかげで、その型のメソッドやプロパティに追加のチェック無しでアクセスできることに注意してください。

val hasPrefix = when(x) {
  is String -> x.startsWith("prefix")
  else -> false
}

whenif-else if連鎖を代替することもできます。 引数が与えられない場合は、分岐条件は単純なbooleanの式となり、分岐はその条件がtrueの場合に実行されます:

when {
  x.isOdd() -> print("x is odd")
  x.isEven() -> print("x is even")
  else -> print("x is funny")
}

以下のシンタックスを使って、whenの対象を変数に捕捉する事が出来ます。

fun Request.getBody() =
    when (val response = executeRequest()) {
        is Success -> response.body
        is HttpError -> throw HttpException(response.status)
    }

whenの対象の所で導入された変数のスコープは、whenの本体の中のみです。

Forループ

forループはイテレータによって提供されるものを何でも繰り返し実行します。 これはC#などの言語のforeachと同等です。 forの構文は次のとおりです:

for (item in collection) print(item)

forの本文をブロックにすることもできます。

for (item: Int in ints) {
  // ...
}

前述したように、 for はイテレータを提供するものを何でも繰り返し実行します。すなわち:

  • メンバ関数や拡張関数の iterator()Iterator<>型をすもの:
    • メンバ関数や拡張関数の next() を持つ
    • メンバ関数や拡張関数でBoolean を返す hasNext() を持つ

これら3つの関数は全て operator としてマークされる必要があります。(訳注:operatorキーワードを指定する必要がある)

数字の範囲を繰り返し実行したい場合は、range式 が使えます:

fun main() { //sampleStart for (i in 1..3) { println(i) } for (i in 6 downTo 0 step 2) { println(i) } //sampleEnd }

rangeや配列のforループはインデックスベースのループにコンパイルされ、 イテレータオブジェクトを作成しません。

もし配列やリストをインデックス付きで繰り返し処理したいならば、以下の方法を使用できる:

fun main() { val array = arrayOf("a", "b", "c") //sampleStart for (i in array.indices) { println(array[i]) } //sampleEnd }

別方法として、ライブラリ関数の withIndex を使用することもできます:

fun main() { val array = arrayOf("a", "b", "c") //sampleStart for ((index, value) in array.withIndex()) { println("$index 番目の要素は $value") } //sampleEnd }

whileループ

whiledo-whileループは与えられた条件が満たされている間、本体を実行し続けます。 両者の違いは条件を確認するタイミングです:

  • whileは条件をチェックし、それが満たされていたら、本体を実行してまた条件チェックに戻ります
  • do-whileは本体を実行し、それから条件をチェックします。もし条件が満たされていたら、ループをもう一度実行します。つまり、do-whileの本体は条件によらず最低でも一回は実行されます。
while (x > 0) {
  x--
}

do {
  val y = retrieveData()
} while (y != null) // y はここで可視(visible)

ループ内でのbreakとcontinue

Kotlinは従来通りの、ループ内の breakcontinue 演算子をサポートしています。Returnとジャンプを参照してください。