この Codelab は、プログラマー向け Kotlin ブートキャンプ コースの一部です。Codelab を順番に進めていくと、このコースを最大限に活用できます。理解度によっては、特定のセクションの概要を読むだけで済む場合があります。このコースは、Kotlin を学習し、オブジェクト指向言語を習得したいプログラマーを対象としています。
はじめに
この Codelab では、Kotlin プログラミング言語の基本(データ型、演算子、変数、制御構造、null 許容変数と null 非許容変数)について学習します。このコースは、オブジェクト指向言語に精通し、Kotlin を学びたいプログラマーを対象としています。
このコースのレッスンは単一のサンプルアプリを構築するものではなく、知識を広げることを目的としていますが、相互に依存しない部分があるため、使い慣れたセクションを省略できます。これらをまとめる例の多くは、水族館のテーマを使用しています。また、アクアリウムのストーリー全文については、Udacity の Profiler 向け Kotlin ブートキャンプ コースで詳細をご覧ください。
前提となる知識
- IntelliJ IDEA でプロジェクトを作成する方法
- IntelliJ IDEA の Kotlin の REPL(Read-Eval-Print Loop)を開いて実行する方法(Tools > Kotlin > Kotlin REPL)
学習内容
- Kotlin のデータ型、演算子、変数の使用方法
- ブール値と条件の操作方法
- null 許容変数と null 非許容変数の違い
- Kotlin での配列、リスト、ループの仕組み
演習内容
- Kotlin の基礎を Kotlin REPL で学ぶ
このタスクでは、Kotlin プログラミング言語の演算子と型について学びます。
ステップ 1: 数値演算子を確認する
- IntelliJ IDEA を開きます(まだ開いていない場合)。
- Kotlin REPL を開くには、[Tools] > [Kotlin] > [Kotlin REPL] を選択します。
他の言語と同様に、Kotlin では、プラス、マイナス、時間、除算に +
、-
、*
、/
を使用します。Kotlin は、Int
、Long
、Double
、Float
など、さまざまな数値型もサポートしています。
- REPL に次の式を入力します。結果を確認するには、1 個ずつ
Control+Enter
(Mac ではCommand+Enter
)キーを押します。
1+1 ⇒ res8: kotlin.Int = 2 53-3 ⇒ res9: kotlin.Int = 50 50/10 ⇒ res10: kotlin.Int = 5 1.0/2.0 ⇒ res11: kotlin.Double = 0.5 2.0*3.5 ⇒ res12: kotlin.Double = 7.0
演算の結果ではオペランドの型が保持されるため、1/2 = 0 ですが、1.0/2.0 = 0.5 となります。
- 整数と小数の組み合わせを変えて、いくつかの式を試してみてください。
6*50 ⇒ res13: kotlin.Int = 300 6.0*50.0 ⇒ res14: kotlin.Double = 300.0 6.0*50 ⇒ res15: kotlin.Double = 300.0
- 番号のメソッドを呼び出します。Kotlin は数値をプリミティブとして保持しますが、数値に対するメソッドはあたかもオブジェクトであるかのように呼び出せます。
2.times(3) ⇒ res5: kotlin.Int = 6 3.5.plus(4) ⇒ res8: kotlin.Double = 7.5 2.4.div(2) ⇒ res9: kotlin.Double = 1.2
ステップ 2: タイプを使用して練習をする
Kotlin では数値型の暗黙的な変換は行われないため、短い値を long 変数に直接割り当てることはできません。また、Byte
を Int
に割り当てることもできません。これは、暗黙的な数値変換がプログラムのエラーの原因になることが多いためです。キャストによって、さまざまなタイプの値をいつでも割り当てることができます。
- 使用可能なキャストを参照するには、REPL で
Int
型の変数を定義します。
val i: Int = 6
- 新しい変数を作成し、上の変数名に続いて
.to
を入力します。
val b1 = i.to
IntelliJ IDEA により、完了となる可能性のある項目のリストが表示されます。このオートコンプリートは、すべての型の変数とオブジェクトで使用できます。
- リストから [
toByte()
] を選択し、変数を出力します。
val b1 = i.toByte()
println(b1)
⇒ 6
- さまざまな型の変数に
Byte
値を割り当てます。
val b2: Byte = 1 // OK, literals are checked statically
println(b2)
⇒ 1
val i1: Int = b2
⇒ error: type mismatch: inferred type is Byte but Int was expected
val i2: String = b2
⇒ error: type mismatch: inferred type is Byte but String was expected
val i3: Double = b2
⇒ error: type mismatch: inferred type is Byte but Double was expected
- エラーを割り当てた課題の場合は、代わりにキャストを行ってください。
val i4: Int = b2.toInt() // OK!
println(i4)
⇒ 1
val i5: String = b2.toString()
println(i5)
⇒ 1
val i6: Double = b2.toDouble()
println(i6)
⇒ 1.0
- Kotlin では、長い数値定数を見やすくするために、数値内でアンダースコアを使用できます。さまざまな数値を入力してください。
val oneMillion = 1_000_000 val socialSecurityNumber = 999_99_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010
ステップ 3: 変数タイプの値を確認する
Kotlin は、変更可能なものと変更不可能なものの 2 種類の変数をサポートします。val
では、値を 1 回だけ割り当てることができます。もう一度割り当てようとすると、エラーが発生します。var
を使って値を割り当て、プログラムの後半で値を変更できます。
val
とvar
を使用して変数を定義し、それらの変数に新しい値を割り当てます。
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned
fish
には var
で値が設定されているため、これを割り当てて、新しい値を割り当てることができます。新しい値を aquarium
に割り当てようとすると、val
で定義されているため、エラーが発生します。
変数に格納する型は、コンパイラがコンテキストから判断できるタイミングです。コロンの表記を使用すると、いつでも変数の型を明示的に指定できます。
- いくつかの変数を定義し、型を明示的に指定します。
var fish: Int = 12
var lakes: Double = 2.5
自分やコンパイラが割り当てた型は、変更できないか、エラーが発生します。
ステップ 4: 文字列について学ぶ
Kotlin の文字列は、他のプログラミング言語の文字列と同じように機能し、文字列に "
を使用して、単一文字に '
を使用します。また、文字列を +
演算子で連結することもできます。文字列テンプレートは、値と組み合わせることで作成できます。$
variable
名は、値を表すテキストに置き換えられます。これを「変数補間」と呼びます。
- 文字列テンプレートを作成します。
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
- 式を含む文字列テンプレートを作成します。他の言語と同様に、値は式の結果である場合があります。中かっこ
{}
を使用して式を定義します。
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants
このタスクでは、Kotlin プログラミング言語でのブール値と条件の確認について学習します。他の言語と同様に、Kotlin にはブール演算子とブール演算子(より小さい、等しい、より大きいなど)があります(<
、==
、>
、!=
、<=
、>=
)。
if
/else
ステートメントを記述する
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
println("Good ratio!")
} else {
println("Unhealthy ratio")
}
⇒ Good ratio!
if
ステートメントで範囲を指定します。Kotlin では、テストする条件で範囲を使用することもできます。
val fish = 50
if (fish in 1..100) {
println(fish)
}
⇒ 50
- 複数のケースを含む
if
を記述します。より複雑な条件の場合は、論理と&&
、論理または||
を使用します。他の言語と同様に、else if
を使用すると複数のケースに対応できます。
if (numberOfFish == 0) {
println("Empty tank")
} else if (numberOfFish < 40) {
println("Got fish!")
} else {
println("That's a lot of fish!")
}
⇒ That's a lot of fish!
when
ステートメントを試す。Kotlin で一連のif
/else if
/else
ステートメントをwhen
ステートメントを使用して記述すると、他の言語のswitch
ステートメントを使用するよりも便利な方法です。when
ステートメントの条件にも範囲を使用できます。
when (numberOfFish) {
0 -> println("Empty tank")
in 1..39 -> println("Got fish!")
else -> println("That's a lot of fish!")
}
⇒ That's a lot of fish!
このタスクでは、null 許容変数と null 非許容変数について学習します。null を含むプログラミング エラーは膨大な数のバグの原因となっています。Kotlin は、null 値が許容されない変数を導入することで、バグの削減を目指しています。
ステップ 1: null 値許容について学習する
デフォルトでは、変数を null
にすることはできません。
Int
を宣言し、null
を割り当てます。
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
- 変数に null を使用できることを示すには、型の後に疑問符演算子
?
を使用します。Int?
を宣言し、null
を割り当てます。
var marbles: Int? = null
リストなどの複雑なデータ型がある場合:
- リストの要素を null にすることもできます。
- リストは null を許可できますが、null ではない場合、その要素を null にすることはできません。
- リストまたは要素の両方を null にすることもできます。
リストやその他の複雑なデータ型については、後のタスクで説明します。
ステップ 2: ??: 演算子
?
演算子を使用して null
をテストできるため、if
/else
ステートメントをいくつも記述する必要がなくなります。
fishFoodTreats
変数がnull
でないか確認する長いコードを記述します。その変数の値を減らします。
var fishFoodTreats = 6
if (fishFoodTreats != null) {
fishFoodTreats = fishFoodTreats.dec()
}
- 次に、Kotlin で
?
演算子を使用して記述する方法を見てみましょう。
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
?:
演算子を使用して null テストを連結することもできます。次の例をご覧ください。
fishFoodTreats = fishFoodTreats?.dec() ?: 0
「fishFoodTreats
」が「null
」でない場合は省略し、使用します。それ以外の場合は、?:
の後に値(0)を使用します。fishFoodTreats
が null
の場合、評価は停止され、dec()
メソッドは呼び出されません。
null ポインタに関する注意点
NullPointerExceptions
が大好きな方は、Kotlin で維持できます。非 null アサーション演算子 !!
(ダブルバン)は、任意の値を非 null 型に変換し、値が null
の場合は例外をスローします。
val len = s!!.length // throws NullPointerException if s is null
このタスクでは、配列とリストについて学習し、Kotlin プログラミング言語でループを作成するさまざまな方法を学びます。
ステップ 1: リストを作成する
リストは Kotlin の基本的な型であり、他の言語のリストに似ています。
listOf
を使用してリストを宣言し、出力します。このリストは変更できません。
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
mutableListOf
を使用して変更できるリストを宣言します。項目を削除する。
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true
remove()
メソッドは、渡されたアイテムを正常に削除すると true
を返します。
ステップ 2: 配列を作成する
他の言語と同様に、Kotlin には配列があります。可変バージョンと不変バージョンがある Kotlin と異なり、Array
に可変バージョンはありません。配列を作成した後、サイズは固定されます。要素を追加または削除するには、新しい配列にコピーする必要があります。
val
と var
の使用に関するルールは、配列でもリストの場合と同じです。
arrayOf
を使用して文字列の配列を宣言します。java.util.Arrays.toString()
配列ユーティリティを使用して出力します。
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
arrayOf
で宣言されている配列では、要素が関連付けられた型を持たないため、型を混在させることが可能です。異なる型の配列を宣言します。
val mix = arrayOf("fish", 2)
- すべての要素に対して 1 つの型で配列を宣言することもできます。
intArrayOf()
を使用して整数の配列を宣言します。他の型の配列には、対応するビルダーまたはインスタンス化関数があります。
val numbers = intArrayOf(1,2,3)
- 2 つの配列を
+
演算子で結合します。
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
- ネストされた配列とリストのさまざまな組み合わせを試してみてください。他の言語と同様に、配列とリストをネストできます。つまり、配列内の配列を挿入すると、配列の配列になりますが、2 つの内容の配列はフラット化されません。配列の要素もリストにでき、リストの要素は配列にすることもできます。
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
⇒ [[I@89178b4, [Atlantic, Pacific], salmon]
最初の要素 numbers
は Array
です。配列ユーティリティを使用して出力しない場合、Kotlin は配列の内容ではなく住所を出力します。
- Kotlin の便利な機能の 1 つは、配列を 0 に初期化する代わりに、コードを使用して初期化できることです。次の例をご覧ください。
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]
初期化コードは中かっこ {}
で囲まれています。コードでは、it
は 0 から始まる配列インデックスを表します。
ステップ 3: ループの作成
これでリストと配列ができたので、要素をループして期待どおりに動作します。
- 配列を作成します。
for
ループを使用して配列を反復処理し、要素を出力します。
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
print(element + " ")
}
⇒ shark salmon minnow
- Kotlin では、要素とインデックスを同時にループできます。次の例をご覧ください。
for ((index, element) in school.withIndex()) {
println("Item at $index is $element\n")
}
⇒ Item at 0 is shark Item at 1 is salmon Item at 2 is minnow
- ステップのサイズや範囲を変えてみてください。アルファベット順で数字の範囲または文字の範囲を指定できます。他の言語と同様に、1 つ前にに進む必要はありません。前の手順に戻るには
downTo
を使用します。
for (i in 1..5) print(i)
⇒ 12345
for (i in 5 downTo 1) print(i)
⇒ 54321
for (i in 3..6 step 2) print(i)
⇒ 35
for (i in 'd'..'g') print (i)
⇒ defg
- ループをいくつか試してみてください。他の言語と同様に、Kotlin には
while
ループ、do...while
ループ、++
演算子と--
演算子があります。Kotlin にはrepeat
ループもあります。
var bubbles = 0
while (bubbles < 50) {
bubbles++
}
println("$bubbles bubbles in the water\n")
do {
bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")
repeat(2) {
println("A fish is swimming")
}
⇒ 50 bubbles in the water 49 bubbles in the water A fish is swimmingA fish is swimming
Kotlin は、演算子、リスト、ループなど、基本的な言語とよく似ていますが、重要な違いがいくつかあります。
以下の機能は、Kotlin では他の言語に慣れているものとは異なる場合があります。
- Kotlin 型は、暗黙的に変換できません。キャスティングを使用します。
val
で宣言されている変数は一度だけ割り当てることができます。- Kotlin 変数はデフォルトで null 許容ではありません。
?
を使用して変数を null 許容にします。 - Kotlin では、
for
ループ内で配列のインデックスと要素を同時にループできます。
次の Kotlin プログラミング構成は、他の言語のものと同様です。
- 配列とリストには、1 つの型または混合型を含めることができます。
- 配列とリストはネストできます。
- ループは
for
、while
、do
/while
、repeat
で作成できます。 when
ステートメントは Kotlin のswitch
ステートメント版ですが、when
の方が柔軟性があります。
Kotlin ドキュメント
このコースに関するトピックについて詳しい情報が必要な場合や、ご不明な点がある場合は、https://kotlinlang.org をご覧ください。
Kotlin のチュートリアル
https://try.kotlinlang.org のウェブサイトには、Kotlin Koans(リッチなチュートリアル)やウェブベースのインタープリタ、サンプルを含むリファレンス ドキュメントが豊富に用意されています。
Udacity コース
このトピックに関する Udacity コースについては、プログラマー向け Kotlin ブートキャンプをご覧ください。
IntelliJ IDEA
IntelliJ IDEA のドキュメントは、JetBrains のウェブサイトにあります。
このセクションでは、インストラクターが主導するコースの一環として、この Codelab に取り組む生徒の課題について説明します。教師は以下のことを行えます。
- 必要に応じて課題を割り当てます。
- 宿題の提出方法を生徒に伝える。
- 宿題を採点します。
教師はこれらの提案を少しだけ使うことができます。また、他の課題は自由に割り当ててください。
この Codelab にご自分で取り組む場合は、これらの課題を使用して知識をテストしてください。
次の質問に答えてください。
問題 1
文字列の不変のリストを宣言するのは次のうちどれですか。
▢ val school = arrayOf("shark", "salmon", "minnow")
▢ var school = arrayOf("shark", "salmon", "minnow")
▢ val school = listOf("shark", "salmon", "minnow")
▢ val school = mutableListOf("shark", "salmon", "minnow")
質問 2
以下のコードが出力されます。for (i in 3..8 step 2) print(i)
▢ 345678
▢ 468
▢ 38
▢ 357
問題 3
このコードの疑問符の目的は何ですか。var rocks: Int? = 3
▢ 変数 rocks
の型は修正されていません。
▢ 変数 rocks
を null に設定できます。
▢ 変数 rocks
を null に設定することはできません。
▢ 変数 rocks
は直ちに初期化されません。
次のレッスンに進みましょう。
他の Codelab へのリンクを含むコースの概要については、プログラマー向け Kotlin ブートキャンプ: コースへようこそをご覧ください。