はじめに
公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。
過去記事はこちら
- Introduction
- Classes
問題
Smart casts
次の Java コードをsmart castとwhen式を使って書き直します。
public int eval(Expr expr) {
if (expr instanceof Num) {
return ((Num) expr).getValue();
}
if (expr instanceof Sum) {
Sum sum = (Sum) expr;
return eval(sum.getLeft()) + eval(sum.getRight());
}
throw new IllegalArgumentException("Unknown expression");
}
修正前のコード
fun eval(expr: Expr): Int =
when (expr) {
is Num -> TODO()
is Sum -> TODO()
else -> throw IllegalArgumentException("Unknown expression")
}
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
問題のポイント
smart castとwhen式を使った問題です。
smart cast
Kotlinでは、ほとんどの場合、明示的なキャスト演算子を使う必要はありません。なぜなら、コンパイラは、不変値に対するis-checkと明示的なキャストを追跡し、必要な場合は自動的に(安全な)キャストを挿入してくれるからです。
fun demo(x: Any) {
if (x is String) {
print(x.length) // x は自動的に String にキャストされる
}
}
コンパイラは賢いので、事前に型チェックをしていればキャストは安全であると知っています。
if (x !is String) return
print(x.length) // x は自動的に String にキャストされる
スマートキャストは、when式やwhileループでも有効です。今回の問題ではこれを使います。
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
when式
when式は、複数の分岐を持つ条件式を定義する場合です。switch文のようなものです。
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
解答例
when式でNum
型の場合は、プロパティvalue
を取得できます。
Sum
型の場合は、Expr
型のプロパティleft
、right
が取得できるので、これらを引数にeval
関数を呼び出し、取得した値を足します。
fun eval(expr: Expr): Int =
when (expr) {
is Num -> expr.value
is Sum -> eval(expr.left) + eval(expr.right)
else -> throw IllegalArgumentException("Unknown expression")
}
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr