2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Kotlin Koans やってみた 6

Last updated at Posted at 2025-01-13

Introduction

Nothing type

問題

常に例外をスローする関数には、戻り値の型として Nothing を使用することができます。
そのような関数を呼び出すと、コンパイラは関数の実行がそれ以降続かないことを前提に処理します。

failWithWrongAge 関数には Nothing 型を戻り値として指定してください。
Nothing 型を指定しない場合、checkAge 関数はコンパイルされません。
これは、コンパイラが年齢が null である可能性を前提としているためです。

解答

import java.lang.IllegalArgumentException

fun failWithWrongAge(age: Int?): Nothing {
    throw IllegalArgumentException("Wrong age: $age")
}

fun checkAge(age: Int?) {
    if (age == null || age !in 0..150) failWithWrongAge(age)
    println("Congrats! Next year you'll be ${age + 1}.")
}

fun main() {
    checkAge(10)
}

解説

Kotlin 公式ドキュメント > The Nothing type

The Nothing type

Kotlin では、すべての式に型があります。たとえば、throw IllegalArgumentException() という式の型は Nothing です。Nothing は Kotlin に組み込まれた型で、すべての型のサブタイプ、いわゆる「ボトム型」と呼ばれるものです。これにより、Nothing は他のどの型が期待される場合でも、戻り値の型やジェネリック型として使用しても型エラーを引き起こすことはありません。

Nothing は Kotlin で特別な型として扱われ、例外を常にスローしたり、無限ループなどで正常に終了しない関数や式を表現するために使用されます。この型は、まだ実装されていない関数や、常に例外をスローするように設計された関数に使用することで、コンパイラやコードを読む人に意図を明確に伝えることができます。関数のシグネチャでコンパイラが Nothing 型を推論すると警告が表示されますが、戻り値の型として明示的に Nothing を定義することで、この警告を回避できます。

以下の Kotlin コードは、Nothing 型の使用例を示しています。このコードでは、関数呼び出しの後のコードが到達不可能としてコンパイラに認識される様子が確認できます。

class Person(val name: String?)

fun fail(message: String): Nothing {
    throw IllegalArgumentException(message)
    // この関数は正常に戻り値を返すことはありません
    // 常に例外をスローします
}

fun main() {
    // 'name' が null の Person インスタンスを作成します
    val person = Person(name = null)
    
    val s: String = person.name ?: fail("Name required")

    // 's' はこの時点で確実に初期化されています
    println(s)
}

/*
Exception in thread "main" java.lang.IllegalArgumentException: Name required
    at FileKt.fail (File.kt:4)
    at FileKt.main (File.kt:13)
    at FileKt.main (File.kt:-1)
*/

Kotlin の TODO() 関数も Nothing 型を使用しており、今後の実装が必要な箇所を明確にするためのプレースホルダーとして役立ちます。

fun notImplementedFunction(): Int {
    TODO("This function is not yet implemented")
}

fun main() {
    val result = notImplementedFunction()
    // これは NotImplementedError をスローします
    println(result)
}

/*
Exception in thread "main" kotlin.NotImplementedError: An operation is not implemented: This function is not yet implemented
    at FileKt.notImplementedFunction (File.kt:2)
    at FileKt.main (File.kt:6)
    at FileKt.main (File.kt:-1)
*/

ご覧のとおり、TODO() 関数は常に NotImplementedError 例外をスローします。

おわりに

Nothing 型って知らなかったな〜。
まだ実装してないよ〜って時に TODO() を使うのね。
TODO("This function is not yet implemented") これは関数未実装のときのテンプレとして使いたい!空で書けたらかっこいいんだけどな〜。あ、でも IntelliJ が気を利かせて入れてくれてたような気がしなくもない・・・


← 前回の記事 | 次回の記事 →

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?