『Kotlinイン・アクション』第2章を読む (その2)
前回に引き続き、Kotlinイン・アクションの第2章「Kotlinの基本」です。
『Kotlinイン・アクション』第2章を読む (その1) - おはようエンジニア
enum
- 列挙型は
enum class
で宣言するenum
の部分はソフトキーワードという扱い(classと組み合わせて意味を持つ)
enum class Color { RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET }
enum class Color (val r: Int, val g: Int, val b: Int){ RED(255, 0, 0), ORANGE(255, 165, 0), ..., VIOLET(238, 130, 238); fun rgb() = (r * 256 + g) * 256 + b }
when
- whenは値を返すので「文」ではなく「式」
- それぞれの分岐でのbreak文は不要
- 複数の値によって分岐できる
fun getWarmth(color: Color) = when(color) { Color.RED, Color.ORANGE, Color.YELLOW -> "warm" Color.GREEN -> "neutral" Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold" }
- 定数の値をインポートするとより簡潔
- ここの1行目の役割がわからない
import ch02.colors.Color import ch02.colors.Color.* fun getWarmth(color: Color) = when(color) { RED, ORANGE, YELLOW -> "warm" GREEN -> "neutral" BLUE, INDIGO, VIOLET -> "cold" }
- when式の引数にオブジェクトも使用できる
- この例は比較の度にインスタンスを生成するのでパフォーマンスはあまりよくない
- 読みにくくなるが引数なしwhen文を使うとパフォーマンスは改善する
// オブジェクトが引数の場合 when (setOf(c1, c2)) { setOf(RED, YELLOW) -> ORANGE ... } // 引数なしの場合 when { (c1 == RED && c2) || (c1 == YELLOW && c2 == RED) -> ORANGE ... }
スマートキャスト
is
によって変数の型をチェックすると明示的なキャストが不要になる
fun eval(e: Expr): Int { if (e is Num) { val n = e as Num // 不要 println("num: ${n.value}") return n.value } else if (e is Sum) { val n = e as Sum // 不要 ... }
whenですっきり表記
fun eval(e: Expr): Int { when (e) { is Num -> { println("num: ${e.value}") e.value } is Sum -> { ... }
while
while
とdo-while
がある- Javaと同じ
for と range
- Kotlin の
for
は Java のfor-each
形式のみ
// 1から100まで (閉区間) for (i in 1..100) { print(i) // 1,2,3,...,100 } // 1から100の直前まで (半開区間) for (i in 1 until 100) { print(i) // 1,2,3,...,99 } // 後進 for (i in 100 downTo 1) { print(i) // 100,99,98,...,1 } // 2ずつ増加 for (i in 1..100 step 2) { print(i) // 1,3,5,...,99 }
- 文字やコレクションでもレンジを作れる
// Character for (c in 'A' .. 'F') { ... } // TreeMap for ((key, value) in myMap) { ... } // ArrayList for ((index, element) in list.withIndex()) { ... }
- !in でレンジ外であることをチェックできる
fun isNotDigit(c: Char) = c !in '0'..'9'
java.lang.Comparable
インターフェイスを実装するとその型のオブジェクトでレンジを作れる
例外処理
throw
は式扱い- 関数定義の後ろに
throws
はいらない - 検査例外と非検査例外は区別しない
- 例外を処理するかどうかは実装者に委ねる
- 理由はJavaの検査例外の処理がボイラープレートになっているため
try
も式- 例外をキャッチしたときに結果を変える実装をシンプルに書ける
val number = try { Integer.parseInt(reader.readLine()) } catch (e: NumberFormatException) { null }
式と文のまとめ
構文 | Java | Kotlin |
---|---|---|
when | 文 | 式 |
if | 文 | 式 |
throw | 文 | 式 |
try | 文 | 式 |
代入 (例: a = 1) | 式 | 文 |
おわりに
2章で基本的な構文について学ぶことができました。
KotlinではJavaで文だったものの一部が式になり、式本体を持つ関数と相性が良さそうな印象です。
特に、when式はかなり柔軟で使い勝手がよさそうです。また、break文を何度も書く必要がないのも嬉しいです。