Kotlin 2.1.0では新しい言語機能がPreviewとして試せるようになっているので、そちらを簡単に紹介したいと思います。
when の Guard conditions
when
の中で条件を追加することができるようになります。
例えば、以下のような定義があります。
enum class ErrorType {
NOT_FOUND,
UNKNOWN
}
sealed interface Result {
data class Success(val value: String) : Result
data class Error(val type: ErrorType) : Result
}
これを when
で Guard conditions を使って書くと以下のようになります。
private fun sample(result: Result) {
when (result) {
is Result.Success -> {
// ...
}
is Result.Error if result.type == ErrorType.NOT_FOUND -> {
// ifを使って条件を追加してる
// ...
}
else -> {
// ...
}
}
}
こんな感じで、 when
の条件に更に条件を追加する感じです。
注意としては Guard conditions では網羅性を確認できないので、以下のような書き方ではエラーになります。
private fun sample(result: Result) {
when (result) {
is Result.Success -> {
}
is Result.Error if result.type == ErrorType.NOT_FOUND -> {
}
is Result.Error if result.type == ErrorType.UNKNOWN -> {
// enumを網羅してるけど、コンパイルエラーになる
}
}
}
そのため、 else
または Guard conditions がないパターンが必要です。
private fun sample(result: Result) {
when (result) {
is Result.Success -> {
}
is Result.Error if result.type == ErrorType.NOT_FOUND -> {
}
is Result.Error -> {
// これで網羅していることになるので成功
}
// else -> {} 上の条件の代わりにコレでも良い
}
}
この機能では他にも when
で else if
が使えるようになっています。
private fun sample(value: String) {
when (value) {
"A" -> {}
"B" -> {}
else if value.length == 1 -> {}
else if value.length > 1 -> {}
}
}
全体的に when
が強化された感じになっています。
Non-local break and continue
ちょっと分かりにくい機能なんですけど、ループ内の break
や continue
がラムダ式内でも可能になりました。
fun sample(values: List<String?>) {
for (value in values) {
value ?: run {
log("$value is null")
// ラムダ式内で continue/break が使える
continue
}
// ...
}
}
(ちょっと良い例がなくて、この例だと普通に if
文を使えば良いんですけど…)
単純に便利になった感じなので、恩恵を受けるケースはあるかなと思います。
Multi-dollar string interpolation
$
を文字列リテラル等で書きたいときの書き方が改善されています。
これまでは以下のように$をリテラルに入れたい場合は、 ${‘$’}
のように書く必要がありました。
fun sample(value: String) {
val message = "${'$'}value = $value"
println(message)
}
この機能を使うとダブルコーテーションの前に $$
と書くことでシンプルにすることができます。
fun sample(value: String) {
val message = $$"$value = $$value"
println(message)
}
コレを使うと変数展開をしたい場合は $$
とする必要があります。
マルチラインのリテラルでも使えます。
fun sample(value: String) {
val message = $$"""
$value = $$value"
""".trimIndent()
println(message)
}
$
がたくさん出てくるような文字列リテラルを作るときは便利そうです。
各機能を有効にするには
上記で紹介した機能はまだデフォルトでは有効ではないので、Gradleなどでコンパイラオプションの設定が必要です。
Gradleでは以下のように設定します。
kotlin {
compilerOptions {
freeCompilerArgs.add("-Xwhen-guards")
freeCompilerArgs.add("-Xnon-local-break-continue")
freeCompilerArgs.add("-Xmulti-dollar-interpolation")
}
}