The Kotlin Programming Language(1-2)

Step1-2:【基礎編】Kotlin言語のキホンをマスターしよう!

TKPLのアウトライン

  • ステップ1:【基礎編】Kotlin言語のキホンをマスターしよう!
    サブトピック1-1:プログラミングの第一歩
    サブトピック1-2:プログラムの流れを操る←今回はここ
    サブトピック1-3:オブジェクト指向って何?

  • ステップ2:【入門編】はじめてのAndroidアプリ開発
    サブトピック2-1:開発環境の準備と初めてのアプリ
    サブトピック2-2:アプリの画面を作ってみよう
    サブトピック2-3:効率的なリスト表示

  • ステップ3:【実践編】機能的なアプリを作るための応用技術
    サブトピック3-1:データを保存する (Data Persistence)
    サブトピック3-2:インターネットと通信する (Networking & Concurrency)
    サブトピック3-3:画面遷移とアーキテクチャ (Navigation & Architecture)

Kotlin基礎解説:第2回 制御構文(if, when, for, 関数)

第1回ではKotlinの変数と型システムについて解説しました。今回はその続きとして、プログラムの実行フローを制御するための主要な構文、すなわち条件分岐繰り返し、そして処理を部品化する関数について掘り下げていきます。

Javaの制御構文と似ている部分もありますが、Kotlinがいかに表現力を高め、コードの簡潔性を追求しているかが随所に見られます。

また最も意識すべきパラダイムシフトは「文 (Statement) から 式 (Expression) へ」という変化です。 Javaでは「命令」だった制御構文の多くが、Kotlinでは「値を返す計算式」として扱えるようになっています。この違いがいかにコードの安全性と簡潔性を高めるか、具体例とともに見ていきましょう。

1. 条件分岐 – if と when

状況に応じて処理の流れを変える条件分岐は、あらゆるプログラムの基本です。Kotlinでは主にifとwhenが用いられます。
Kotlinの条件分岐は、単なる分岐命令ではなく、結果を「返す」ことができるのが最大の特徴です。

1.1 if “式”

Kotlinの if は、Javaの if 文と同様に利用できますが、式 (Expression) として値を返せる点が決定的に異なります。
そのため、Kotlinには三項演算子 (condition ? true : false) が存在しません。 if 式そのものが三項演算子の役割を兼ねているからです。これにより、「普通のif」と「三項演算子」で書き方を迷う必要がなくなりました。

val score = 85
// if式の結果を直接変数に代入。
// Javaの `String result = (score >= 80) ? "Pass" : "Fail";` に相当。
val result = if (score >= 80) {
    println("Great job!") // ブロック内に処理を書くことも可能
    "Pass" // 最後に評価された式が戻り値となる
} else {
    "Fail"
}

1.2 when “式”

when は Javaの switch 文を現代的に再設計したものです。break が不要であるため、「break忘れによるバグ」から解放されます。
when の真価はスマートキャストとの組み合わせで発揮されます。is を使って型チェックを行うと、その分岐内では自動的にその型として扱われます。

val input: Any = "Hello Kotlin"

val message = when (input) {
    // 値によるマッチング
    100 -> "Full Score"
    in 90..99 -> "High Score"
    
    // 型によるマッチングとスマートキャスト
    // ここでは自動的に String として扱われるため、.length が呼び出せる
    is String -> "It's a string with length ${input.length}"
    
    // 複雑な条件式(引数なしwhen)
    else -> "Unknown"
}

Point: when を式として(値を返すために)使う場合、コンパイラは「全てのパターンを網羅しているか」を厳密にチェックします。そのため、else 句が必須になるケースが大半です。これが予期せぬ抜け漏れを防ぎます。

2. 繰り返し処理 – for ループ

Kotlinのforループは、Javaの拡張for文 (for-each) と同様のシンプルさで、範囲やコレクションの要素を反復処理します。
Kotlinの for は、イテレータを提供するあらゆるものを反復処理できます。 Javaの for (int i=0; i < 10; i++) のようなC言語スタイルのループは廃止され、範囲 (Range) を使った記述に統一されました。

// 基本:1から5まで(1 <= i <= 5)
for (i in 1..5) { ... }

// 未満:1から10未満(1 <= i < 10)
// 配列のインデックスアクセスなどで重宝する
for (i in 1 until 10) { ... }

// 降順:5から1まで(5 >= i >= 1)
for (i in 5 downTo 1) { ... }

// インデックス付きで要素を取り出す
val items = listOf("A", "B", "C")
for ((index, value) in items.withIndex()) {
    println("$index: $value")
}

3. 処理の部品化 – 関数

関数は、特定のタスクを実行するコードブロックに名前をつけたものです。funキーワードで定義します。Kotlinの関数定義は、その構文に特徴があります。

// デフォルト引数:値を省略した場合の初期値を設定できる
fun displayUser(name: String, age: Int = 20, isAdmin: Boolean = false) {
    println("User: $name, Age: $age, Admin: $isAdmin")
}

fun main() {
    // 全引数を指定
    displayUser("Alice", 25, true)
    
    // デフォルト値を利用
    displayUser("Bob") // age=20, isAdmin=false が適用される
    
    // 名前付き引数:引数の順番を気にせず、特定の引数だけ指定できる
    displayUser(name = "Charlie", isAdmin = true) 
}

単一式関数 (Single-Expression Function): 処理が式一つで終わる場合、{}return を省略し、= でつなぐことができます。戻り値の型も推論されるため、非常に簡潔です。

fun square(x: Int) = x * x

4. 学習中のQ&A

本トピックの学習を進めるうえで私がGeminiに対して投げた質問とそれに対する回答をまとめました。

Q. ifが「式」なのは分かりましたが、値を返す必要がない従来の「if文」はどう定義するのですか?

Geminiの回答:特別な構文はなく、全く同じ書き方で「文」として機能します。

Kotlinの設計思想では、「すべての制御構文は基本的に値を返す(式である)」ことになっています。 しかし、その戻り値を変数に代入せずに無視すれば、それは従来のJavaにおける「if文」と同じ振る舞いになります。

技術的に詳しく言うと、値を返すつもりがない if ブロックは、Unit という特別な型(Javaの void に相当するオブジェクト)を返しています。 「Unit を返しているが、誰もそれを受け取らない」という状態が、すなわち「文(ステートメント)」として機能している状態です。

// パターンA:式として使用(値を受け取る)
val msg = if (score > 60) "OK" else "NG"

// パターンB:文として使用(値を受け取らない=従来のif文)
if (score > 60) {
    println("OK") 
    // 実際にはここで Unit オブジェクトが返されているが、捨てられる
}

Q. 文字列テンプレートの$iと${i}の違いは?

Geminiの回答:$の後に変数名を直接記述するのが基本です(例: $i)。ただし、”${i}gold”のように変数の直後に他の文字列が続く場合や、”${price * quantity}”のように変数を含む式を評価したい場合は、{}で囲んで変数の範囲を明示する必要があります。

Q. 「関数(Function)」と「メソッド(Method)」の違いは?

Geminiの回答:「メソッド」は「関数」の一種で、特定のクラスに属している関数を指します。Kotlinでは、Javaと異なり、クラスに属さない「トップレベル関数」をファイルに直接定義できます。本記事で紹介したaddやmultiplyはトップレベル関数です。

Q. 関数の戻り値の型を、Javaと違って引数の後に記述するのはなぜ?

Geminiの回答:これはKotlinの「名前が先、型が後(name: Type)」という一貫した設計思想に基づいています。変数宣言(val name: String)と同じルールであり、左から右へ自然に読める可読性の高さや、型推論との相性の良さといったメリットがあります。

5. まとめ

本記事では、Kotlinの主要な制御構文について解説しました。

  • ifとwhenは、文としてだけでなく値を返すとして機能し、コードを簡潔にする。
  • whenは、Javaのswitchよりも遥かに柔軟で強力な分岐処理が可能。
  • forループは、範囲やコレクションを直感的に反復処理できる。
  • 関数定義は、型推論の恩恵も受けられる、簡潔で読みやすい構文を持つ。

これらの構文は、Kotlinがいかにプログラマの記述量を減らし、コードの可読性を高めることを重視しているかを示しています。

櫟原侑祐

 櫟原侑祐

スキル:Java/SpringBoot/Spring/Kotlin/Bootstrap/Thymeleaf/HTML/CSS/JavaScript/TypeScript/Angular/MySQL/PostgreSQL/MongoDB/Eclipse/Spring Tool Suite4/Android Studio/A5:SQL Mk-2/MongoDB Compass/GitHub

コメント

この記事へのコメントはありません。

関連記事