プログラミング · Kotlin
Kotlin構文のタイピング練習
Kotlin の構文を、初級から上級までの5つのリスト(163個)で打って覚えます。fun main、val と var、null 安全、文字列テンプレート、式としての if・when、Unit と Nothing などを、コードの形で練習できます。
5リスト・163語
無料・ログインなしで練習できます。押すとこのパックをフォローし、すぐに練習が始まります。
収録している言葉
Kotlin構文(初級1)
| 打つ言葉 | 意味・補足 |
|---|---|
| fun main() { println("Hello, Kotlin!") } | fun main():実行開始の関数(関数をトップレベルに定義可能) / コード例の利用:断片を適切な場所へ配置(多くの例は関数内の断片。未定義の変数・型・関数・import等を補って利用) |
| fun greet() { } | fun:関数定義 |
| println("Hello") | println:表示して改行(標準ライブラリ) |
| package example.app | package:パッケージ宣言 |
| // コメント | //:1行コメント |
| /* コメント */ | /* ... */:複数行コメント(入れ子にできる) |
| val age = 20 | val:再代入できない変数(参照先の内部まで変更不可になるわけではない) |
| var count = 0 | var:再代入できる変数 |
| val age: Int = 20 | 名前: 型:型を明示 |
| count = 1 | =:代入(countはvarで宣言済み) |
| const val MAX = 100 | const val:コンパイル時定数(トップレベル・object・companion object内等。型と初期値に制約) |
| val n: Long = 100L | Byte / Short / Int / Long:整数 |
| val c: Char = 'A' | Char:UTF-16コード単位(すべてのUnicode文字が1つのCharで表せるわけではない) |
| val value: Any = 1 | Any:非null型の共通の上位型(nullも扱うならAny?) |
| count += 2 | += / -=:計算と代入(型によって代入演算子関数として処理) |
| count++ | ++ / --:1増減 |
| else -> "不明" | else ->:その他の場合(whenブロック内で使用) |
| if (done) break | break:ループを抜ける(ループ内) |
| if (skip) continue | continue:次の反復へ(ループ内) |
| return result | return 値:値を返して終了 |
| val first = items[0] | items[i]:要素アクセス(範囲外では例外) |
| val n = items.size | size:要素数 |
| names.add("C") | add:要素追加(MutableList等) |
| names[0] = "New" | 添字への代入:要素更新(MutableList・配列等) |
| this.name = name | this:現在のインスタンス(代入先はvar等の変更可能なプロパティ) |
| open class Animal | open class:継承可能なクラス(通常のクラスは既定でfinal) |
| class Dog: Animal() | : 親クラス():クラス継承 |
| super.speak() | super:親の実装を呼ぶ(対応する実装があるメンバー内) |
| public class User | public:公開(通常の既定値) |
| internal class Helper | internal:同一モジュール内で公開 |
| require(age >= 0) | require:引数等の前提条件(不成立ならIllegalArgumentException) |
| check(ready) | check:状態の前提条件(不成立ならIllegalStateException) |
| delay(100) | delay:スレッドを占有せず待機(中断可能なコンテキストで使用) |
Kotlin構文(初級2)
| 打つ言葉 | 意味・補足 |
|---|---|
| import kotlin.math.sqrt | import:型・関数等を読み込む |
| /** 利用者の情報。 */ | /** ... */:KDocコメント(宣言の前に配置) |
| val n = 1; println(n) | 文末のセミコロン省略:通常の文の区切り(通常は行末の;が不要) |
| val n = age.toLong() | toLong():数値型変換(通常、数値型間の代入変換を明示) |
| val n = "123".toInt() | toInt():文字列を整数へ(形式が不正なら例外) |
| val f = 0.5f; val d = 0.5 | Float / Double:浮動小数点数 |
| val ok: Boolean = true | Boolean:真偽値 |
| val name: String = "Pomo" | String:文字列(文字列自体は不変) |
| val remainder = 10 % 3 | + - * / %:加減乗除・余り(整数同士の除算は小数部を切り捨て) |
| val same = name == "Pomo" | ==:内容に基づく等値比較(equalsに基づく。型による特性がある) |
| val sameReference = a === b | ===:参照の同一性(プリミティブ相当値等の同一性に依存しない) |
| val adult = age >= 20 | < <= > >=:大小比較 |
| val valid = age in 18..65 | in / !in:所属判定(範囲・コレクション等に使用) |
| fun double(n: Int) = n * 2 | 式本体:単一式の関数(戻り値型を推論可能) |
| greet(name = "Pomo") | 名前付き引数:引数名を指定 |
| var name: String ? = null | 型?:nullを許容(String等の非null型にはnullを代入不可) |
| val actual = name?: return | ?: return:nullなら早期return(関数内で戻り値型に合わせて使用) |
| val length = name!!.length | !!:非nullアサーション(nullなら例外) |
| val nums = Array(3) { 0 } | Array(長さ) { 初期値 }:長さを指定した配列(この例はArray<Int>) |
| scores["Pomo"] = 120 | map[key] = value:Mapに追加・更新(MutableMap) |
| val score = scores["Pomo"] | map[key]:Mapの値を取得(キーがなければ通常null) |
| names.forEach(::println) | ::関数:関数参照 |
| class User(val name: String) | valプロパティ:読み取り専用プロパティ |
| class User(var age: Int) | varプロパティ:変更可能なプロパティ |
| protected fun work() { } | protected:クラス内部・サブクラス向け(トップレベル宣言には使えない) |
| private fun helper() { } | private:宣言した範囲に限定(トップレベルでは同じファイル内) |
| val(name, age) = user | 分解宣言:コンポーネントを変数へ(componentN関数に基づく) |
| val text = value as String | as:キャスト(型が合わなければ例外) |
| val text = value as ? String | as?:安全キャスト(型が合わなければnull) |
| class Box<T>(val value: T) | class Box<T>:型パラメーター付きクラス |
| val n = name.run { length } | run:対象をthisとして処理し結果を返す(レシーバーなしの形式もある) |
| error("想定外の状態") | error:IllegalStateExceptionを送出(戻り値型はNothing) |
| runBlocking { delay(100) } | runBlocking:スレッドをブロックして完了を待つ(通常のsuspend処理から不用意に使わない) |
Kotlin構文(中級)
| 打つ言葉 | 意味・補足 |
|---|---|
| val n = "abc".toIntOrNull() | toIntOrNull():失敗時にnullとなる変換(結果はInt?) |
| val n: Int; n = 1; println(n) | 初期化:使用前に値を設定(変数・プロパティは適切な初期化が必要) |
| val message = "こんにちは、$name" | $変数:文字列テンプレート |
| val text = """1行目 2行目""" | """...""":raw文字列(改行を含められる。バックスラッシュのエスケープは解釈しない) |
| val ok = enabled && !blocked | && || !:論理演算(&&と||は短絡評価) |
| for (i in 0..4) println(i) | ..:両端を含む範囲(0〜4) |
| for (i in 0..<5) println(i) | ..<:上端を含まない範囲(0以上5未満) |
| for (i in 0 until 5) println(i) | until:上端を含まない範囲(0以上5未満) |
| for (i in 5 downTo 1) println(i) | downTo:降順の範囲 |
| for (i in 0..10 step 2) println(i) | step:刻み幅(正の刻み幅を指定) |
| while (count < 5) { count++ } | while:条件が真の間 |
| do { count++ } while (count < 5) | do / while:最低1回実行 |
| val length: Int ? = name?.length | ?.:安全呼び出し(nullなら結果はnull) |
| val displayName = name?: "Guest" | ?::Elvis演算子(左辺がnullの場合のみ右辺) |
| name?.let { println(it.length) } | ?.let:非null時だけ処理(letは標準ライブラリ関数) |
| val items = arrayOf("A", "B") | arrayOf:配列(標準ライブラリ) |
| val nums = intArrayOf(1, 2, 3) | intArrayOf:IntArray |
| val names = listOf("A", "B") | listOf:読み取り専用List(完全な不変性の保証とは別) |
| val tags = setOf("A", "B") | setOf:重複しない集合 |
| val tags = mutableSetOf("A") | mutableSetOf:変更可能な集合 |
| val scores = mapOf("Pomo" to 100) | mapOf / to:キーと値の対応(toはPairを作る標準関数) |
| val double = { x: Int -> x * 2 } | { 引数 -> 本体 }:ラムダ式 |
| names.forEach { println(it) } | forEach:各要素に処理 |
| val user = User("Pomo", 20) | インスタンス作成:クラスのインスタンス(newを書かない) |
| val updated = user.copy(age = 21) | copy:一部を変えてコピー(浅いコピー。内部参照は共有) |
| val notString = value !is String | !is:指定型でないことを判定 |
| val n = name.let { it.length } | let:対象をitとして処理し結果を返す(通常のit名。ラムダ引数名を変更可能) |
| val n = with (name) { length } | with:指定対象をthisとして処理(ラムダの結果を返す) |
| val name by lazy { "Pomo" } | by lazy:初回アクセス時に初期化(委譲プロパティ) |
| resource.use { r -> println(r) } | use:リソースを自動クローズ(対応するリソース型に使用。プラットフォームに依存) |
| launch { println("実行") } | launch:結果値のない処理を開始(CoroutineScope内で使用) |
| val result = async { "完了" } | async:結果値のある処理を開始(CoroutineScope内で使用。Deferredを返す) |
| val message = result.await() | await:結果を待つ(suspend関数等から呼ぶ) |
Kotlin構文(上級1)
| 打つ言葉 | 意味・補足 |
|---|---|
| fun greet(): Unit { println("Hello") } | Unit:意味のある結果を返さない型(通常は戻り値型を省略) |
| val detail = "長さは${name.length}です" | ${式}:式を文字列へ埋め込む |
| for (item in items) { println(item) } | for (item in items):要素を順に処理(Javaの3部構成forはない) |
| fun greet(name: String) { println(name) } | Unitの関数:意味のある結果を返さない |
| fun outer() { fun inner() { }; inner() } | ローカル関数:関数内に関数を定義 |
| if (name != null) { println(name.length) } | nullチェック:スマートキャスト(途中で変化しないと判断できる等の条件が必要) |
| val names = mutableListOf("A", "B") | mutableListOf:変更可能List(valでも要素の変更は可能) |
| val scores = mutableMapOf<String, Int>() | mutableMapOf:変更可能Map |
| val score = scores.getOrDefault("Pomo", 0) | getOrDefault:キーがなければ既定値(登録値がnullの場合はそのnullを返す) |
| val double: (Int) -> Int = { it * 2 } | it:単一引数の暗黙名(引数を明示しない単一引数ラムダ) / (引数型) -> 戻り値型:関数型 |
| val result = names.filter { it.length >= 3 } | filter:絞り込み / 末尾ラムダ:最後の関数型引数を括弧外へ |
| val result = names.map { it.uppercase() } | map:各要素を変換 |
| val ok = names.any { it.isEmpty() } | any:1つでも条件を満たすか |
| val ok = names.all { it.isNotEmpty() } | all:すべて条件を満たすか(空コレクションではtrue) |
| val result = names.sortedBy { it.length } | sortedBy:指定値で並べ替え |
| val groups = names.groupBy { it.length } | groupBy:指定キーで分類 |
| val isAdult: Boolean get() = age >= 20 | get():カスタムgetter(クラス内。ageは定義済み) |
| open class Animal { open fun speak() { } } | open fun:オーバーライド可能なメンバー |
| abstract class Animal { abstract fun speak() } | abstract class / fun:抽象クラス・抽象関数 |
| interface Greeter { fun greet(): String } | interface:インターフェース |
| enum class Status { TODO, DOING, DONE } | enum class:値を限定した列挙型 |
| object Config { val appName = "App" } | object:名前付きシングルトン |
| if (value is String) println(value.length) | is:型判定(条件下でスマートキャスト) |
| class Box<T : Number>(val value: T) | T : Number:型パラメーターの上限 |
| interface Source<out T> { fun get(): T } | out T:宣言側の共変(主にTを出力する型) |
| interface Sink<in T> { fun put(value: T) } | in T:宣言側の反変(主にTを入力する型) |
| fun count(items: List<*>) = items.size | List<*>:スタープロジェクション(型引数を特定しない) |
| fun String.greet() = "こんにちは、$this" | fun 型.関数:拡張関数(型自体を変更するわけではない。静的に解決) |
| val copy = names.also { println(it.size) } | also:付随処理をして対象自身を返す(対象は通常it) |
| class User { lateinit var name: String } | lateinit var:初期化を後へ延ばす(初期化前アクセスは例外。非nullのvar。プリミティブ相当型等には不可) |
| throw IllegalArgumentException("説明") | throw:例外送出 |
| val result = listOf(1, 2).map { it * 2 } | 構文とライブラリ:言語機能とAPIの区別(コレクション・スコープ関数は標準ライブラリ。多くのコルーチンAPIは追加ライブラリ) |
Kotlin構文(上級2)
| 打つ言葉 | 意味・補足 |
|---|---|
| fun fail(): Nothing = throw IllegalStateException("失敗") | Nothing:正常に戻らない処理の型 |
| val label = if (age >= 20) { "成人" } else { "未成年" } | if / else:条件分岐・値の選択(三項演算子はなくif式を使う) |
| val label = when (role) { "admin" -> "管理者"; "member", "guest" -> "一般利用者"; else -> "不明" } | when (値):値で分岐(式として使う場合は網羅が必要) |
| val result = when { score >= 80 -> "優"; score >= 60 -> "良"; else -> "再挑戦" } | when { 条件 -> ... }:条件を順に判定 |
| val label = when (n) { in 1..10 -> "範囲内"; else -> "範囲外" } | when内のin:範囲で分岐 |
| val label = when (value) { is String -> "文字列"; else -> "その他" } | when内のis:型で分岐 |
| for ((index, value) in items.withIndex()) { println("$index: $value") } | withIndex():添字と値 |
| fun add(a: Int, b: Int): Int { return a + b } | fun 名前(引数): 型:戻り値ありの関数 |
| fun greet(name: String = "Guest") { println(name) } | デフォルト引数:省略時の値 |
| fun sum(vararg values: Int): Int = values.sum() | vararg:可変長引数 |
| val numbers = intArrayOf(1, 2); val total = sum( * numbers) | *配列:可変長引数へ展開(スプレッド演算子) |
| val result = names.find { it.startsWith("A") } | find:最初の一致(なければnull) |
| val result = names.asSequence().filter { it.length >= 3 }.toList() | asSequence:遅延処理するSequence |
| val result = names.filter { it.length >= 3 }.map { it.uppercase() } | 処理の連結:絞り込みと変換 |
| class User(val name: String, var age: Int) { fun greet() = "こんにちは、$name"; fun birthday() { age++ } } | class / 主コンストラクター:クラス定義 |
| class User(val age: Int) { init { require(age >= 0) } } | init:初期化処理 |
| class User(val name: String) { constructor(): this("Guest") } | constructor / this:副コンストラクター |
| var age: Int = 0 set(value) { require(value >= 0); field = value } | set(value) / field:カスタムsetter(fieldはアクセサー内のバッキングフィールド) |
| class Dog: Animal() { override fun speak() { println("わん") } } | override fun:オーバーライド(親側に対応するopen等のメンバーが必要) |
| class User(val name: String) : Greeter { override fun greet() = "こんにちは、$name" } | : インターフェース:実装 |
| data class User(val name: String, val age: Int) | data class:データ用クラス(equals・hashCode・toString・copy等を生成) |
| sealed interface Result { data class Success(val value: String) : Result; data class Failure(val message: String) : Result } | sealed interface:継承関係を制限した状態型(直接のサブタイプに同一パッケージ・モジュール等の制約) |
| class User { companion object { const val DEFAULT_NAME = "Guest" } } | companion object:クラスに関連するメンバー(Javaのstaticと完全に同じ仕組みではない) |
| val greeter = object: Greeter { override fun greet() = "Hello" } | object : 型:無名オブジェクト |
| fun <T> first(items: List<T>): T = items[0] | fun <T>:型パラメーター付き関数(空Listでは例外) |
| val names = mutableListOf<String>().apply { add("Pomo") } | apply:設定して対象自身を返す(対象はthis) |
| val number = try { text.toInt() } catch (e: NumberFormatException) { 0 } | try / catch:例外処理と値の選択(検査例外の捕捉・宣言は強制されない) |
| try { work() } finally { println("後片付け") } | finally:後片付け(プロセス強制終了等で実行されない場合もある) |
| suspend fun greet() { delay(100); println("Hello") } | suspend fun:中断可能な関数(suspendは言語構文。delayはkotlinx.coroutines。自動的に別スレッドにはならない) |
| suspend fun work() = coroutineScope { launch { delay(100) } } | coroutineScope:子の完了を待つスコープ(kotlinx.coroutinesの依存・importが必要) |
| val text = withContext(Dispatchers.IO) { "完了" } | withContext:コンテキストを切り替える(ブロッキングI/O等は適切なDispatcherで実行) |
| import kotlinx.coroutines.*; suspend fun main() = coroutineScope { val result = async { delay(100); "完了" }; println(result.await()) } | コルーチンの実行例:asyncの結果を待つ(kotlinx-coroutines-coreへの依存が必要) |