プログラマー向け Kotlin ブートキャンプ 2: Kotlin の基本

この Codelab は、プログラマー向け Kotlin ブートキャンプ コースの一部です。このコースを最大限に活用するには、Codelab を順番に進めることをおすすめします。理解度によっては、特定のセクションの概要を読むだけで済む場合があります。このコースは、オブジェクト指向言語の知識があり、Kotlin を学習したいプログラマーを対象としています。

はじめに

この Codelab では、Kotlin プログラミング言語の基本(データ型、演算子、変数、制御構造、null 許容変数と非 null 許容変数)について学習します。このコースは、オブジェクト指向言語の知識があり、Kotlin を習得したいプログラマーを対象としています。

このコースのレッスンは、1 つのサンプルアプリを作成するのではなく、知識を深めるように設計されています。また、各レッスンは半独立しているため、よく知っているセクションは読み飛ばすことができます。これらの例を関連付けるため、多くは水族館をテーマにしています。水族館の物語の全体像を確認したい場合は、Udacity の Kotlin ブートキャンプ(プログラマー向け)コースをご覧ください。

前提となる知識

  • IntelliJ IDEA でプロジェクトを作成する方法
  • IntelliJ IDEA の Kotlin の REPL(Read-Eval-Print Loop)でコードを開いて実行できる([Tools] > [Kotlin] > [Kotlin REPL])。

学習内容

  • Kotlin のデータ型、演算子、変数の使用方法
  • ブール値と条件を操作する方法
  • null 値許容変数と null 値非許容変数の違い
  • Kotlin での配列、リスト、ループの仕組み

演習内容

  • Kotlin REPL を使用して Kotlin の基本を学ぶ

このタスクでは、Kotlin プログラミング言語の演算子と型について学習します。

ステップ 1: 数値演算子を確認する

  1. IntelliJ IDEA を開きます(まだ開いていない場合)。
  2. Kotlin REPL を開くには、[Tools] > [Kotlin] > [Kotlin REPL] を選択します。

他の言語と同様に、Kotlin では、加算、減算、乗算、除算に +-*/ を使用します。Kotlin は、IntLongDoubleFloat など、さまざまな数値型もサポートしています。

  1. REPL に次の式を入力します。結果を確認するには、それぞれの後に 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 になります。

  1. 整数と小数のさまざまな組み合わせで式を試してみます。
6*50
⇒ res13: kotlin.Int = 300

6.0*50.0
⇒ res14: kotlin.Double = 300.0

6.0*50
⇒ res15: kotlin.Double = 300.0
  1. 数値に対してメソッドを呼び出します。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 では数値型間の暗黙的な変換は行われないため、short 値を long 変数に直接代入したり、ByteInt に代入したりすることはできません。これは、暗黙的な数値変換がプログラムのエラーの一般的な原因であるためです。キャストを使用すると、常に異なる型の値を割り当てることができます。

  1. 可能なキャストを確認するには、REPL で Int 型の変数を定義します。
val i: Int = 6
  1. 新しい変数を作成し、上記の変数名を入力してから .to を入力します。
val b1 = i.to

IntelliJ IDEA に候補のリストが表示されます。この自動補完は、任意の型の変数とオブジェクトに対して機能します。

  1. リストから toByte() を選択し、変数を印刷します。
val b1 = i.toByte()
println(b1)
⇒ 6
  1. 異なる型の変数に 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
  1. エラーが返された割り当てについては、代わりにキャストを試してください。
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
  1. 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 の場合は、値を割り当てて、後でプログラム内で値を変更できます。

  1. valvar を使用して変数を定義し、新しい値を代入します。
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned

fishvar で定義されているため、値を割り当ててから新しい値を割り当てることができます。aquariumval で定義されているため、新しい値を割り当てようとするとエラーが発生します。

変数に格納する型は、コンパイラがコンテキストから判断できる場合に推論されます。必要に応じて、コロン表記を使用して変数の型を明示的に指定することもできます。

  1. 変数をいくつか定義し、型を明示的に指定します。
var fish: Int = 12
var lakes: Double = 2.5

型がユーザーまたはコンパイラによって割り当てられると、型を変更することはできません。変更しようとするとエラーが発生します。

ステップ 4: 文字列について学ぶ

Kotlin の文字列は、他のプログラミング言語の文字列とほぼ同じように機能します。文字列には "、単一文字には ' を使用し、+ 演算子で文字列を連結できます。文字列テンプレートは、値と組み合わせて作成できます。$variable という名前は、値を表すテキストに置き換えられます。これを変数補間と呼びます。

  1. 文字列テンプレートを作成します。
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
  1. 式を含む文字列テンプレートを作成します。他の言語と同様に、値は式の結果にすることができます。中かっこ {} を使用して式を定義します。
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants

このタスクでは、Kotlin プログラミング言語のブール値と条件のチェックについて学習します。他の言語と同様に、Kotlin にはブール値とブール演算子(小なり、等しい、大なりなど(<==>!=<=>=))があります。

  1. if/else ステートメントを記述します。
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}
⇒ Good ratio!
  1. if ステートメントで範囲を試します。Kotlin では、テストする条件で範囲を使用することもできます。
val fish = 50
if (fish in 1..100) {
    println(fish)
}
⇒ 50
  1. 複数のケースを含む 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!
  1. when ステートメントを試してみます。Kotlin では、if/else if/else 文のシーケンスをより簡単に記述する方法があります。他の言語の switch 文に似た when 文を使用します。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 にできません。

  1. Int を宣言し、null を割り当てます。
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
  1. 型に続けて疑問符演算子 ? を使用すると、変数が null になる可能性があることを示します。Int? を宣言し、null を割り当てます。
var marbles: Int? = null

リストなどの複雑なデータ型がある場合:

  • リストの要素に null 値を許容できます。
  • リストが null であることは許容されますが、null でない場合、その要素は null にできません。
  • リストと要素の両方を null にできます。

リストやその他の複雑なデータ型については、後のタスクで説明します。

ステップ 2: ? について学習する?: 演算子

? 演算子を使用して null をテストできるため、多くの if/else ステートメントを記述する手間が省けます。

  1. fishFoodTreats 変数が null でないかどうかを確認するために、コードを長く記述します。次に、その変数をデクリメントします。
var fishFoodTreats = 6
if (fishFoodTreats != null) {
    fishFoodTreats = fishFoodTreats.dec()
}
  1. 次に、? 演算子を使用した Kotlin の記述方法を見てみましょう。
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
  1. ?: 演算子を使用して null テストを連結することもできます。次の例をご覧ください。
fishFoodTreats = fishFoodTreats?.dec() ?: 0

これは、「fishFoodTreatsnull でない場合は、デクリメントして使用する。それ以外の場合は、?: の後の値(0)を使用する」の短縮形です。fishFoodTreatsnull の場合、評価は停止し、dec() メソッドは呼び出されません。

null ポインタに関する注意点

NullPointerExceptions が本当に好きなら、Kotlin ではそれらを保持できます。null 以外の型アサーション演算子 !!(二重の感嘆符)は、任意の値を null 以外の型に変換し、値が null の場合は例外をスローします。

val len = s!!.length   // throws NullPointerException if s is null

このタスクでは、配列とリストについて学習し、Kotlin プログラミング言語でループを作成するさまざまな方法について学習します。

ステップ 1: リストを作成する

リストは Kotlin の基本的な型であり、他の言語のリストと似ています。

  1. listOf を使用してリストを宣言し、出力します。このリストは変更できません。
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
  1. mutableListOf を使用して変更可能なリストを宣言します。アイテムを削除します。
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true

remove() メソッドは、渡されたアイテムを正常に削除すると true を返します。

ステップ 2: 配列を作成する

他の言語と同様に、Kotlin にも配列があります。可変バージョンと不変バージョンがある Kotlin のリストとは異なり、Array には可変バージョンはありません。配列を作成すると、サイズは固定されます。新しい配列にコピーする場合を除き、要素を追加または削除することはできません。

valvar の使用に関するルールは、配列の場合もリストの場合も同じです。

  1. arrayOf を使用して文字列の配列を宣言します。java.util.Arrays.toString() 配列ユーティリティを使用して出力します。
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
  1. arrayOf で宣言された配列には要素に関連付けられた型がないため、型を混在させることができます。これは便利です。異なる型の配列を宣言します。
val mix = arrayOf("fish", 2)
  1. すべての要素に 1 つの型を使用して配列を宣言することもできます。intArrayOf() を使用して整数の配列を宣言します。他の型の配列にも対応するビルダーまたはインスタンス化関数があります。
val numbers = intArrayOf(1,2,3)
  1. + 演算子を使用して 2 つの配列を結合します。
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
  1. ネストされた配列とリストのさまざまな組み合わせを試してみましょう。他の言語と同様に、配列とリストをネストできます。つまり、配列内に配列を配置すると、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]

最初の要素 numbersArray です。配列ユーティリティを使用して出力しない場合、Kotlin は配列の内容ではなくアドレスを出力します。

  1. Kotlin の優れた機能の 1 つは、配列を 0 に初期化するのではなく、コードで初期化できることです。次の例を試してください。
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]

初期化コードは中かっこ {} の間にあります。コードでは、it は配列インデックス(0 から始まる)を指します。

ステップ 3: ループを作成する

リストと配列ができたので、要素のループ処理は想定どおりに機能します。

  1. 配列を作成します。for ループを使用して配列を反復処理し、要素を出力します。
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}
⇒ shark salmon minnow
  1. 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. さまざまなステップサイズと範囲を試してください。数字または文字の範囲をアルファベット順で指定できます。他の言語と同様に、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
  1. ループをいくつか試してみましょう。他の言語と同様に、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 で宣言された変数には 1 回だけ代入できます。
  • Kotlin 変数は、デフォルトでは null 許容ではありません。? を使用して変数を null 値許容にします。
  • Kotlin では、for ループで配列のインデックスと要素を同時にループできます。

次の Kotlin プログラミング構造は、他の言語の構造と似ています。

  • 配列とリストには、単一の型または混合型を指定できます。
  • 配列とリストはネストできます。
  • forwhiledo/whilerepeat を使用してループを作成できます。
  • 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 はすぐに初期化しないでください。

次のレッスンに進みます。3. 関数

他の Codelab へのリンクを含むコースの概要については、「プログラマー向け Kotlin ブートキャンプ: コースへようこそ」をご覧ください。