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

この 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: 数値演算子を確認する

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

他の言語と同様に、Kotlin では、プラス、マイナス、時間、除算に +-*/ を使用します。Kotlin は、IntLongDoubleFloat など、さまざまな数値型もサポートしています。

  1. 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 となります。

  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 では数値型の暗黙的な変換は行われないため、短い値を 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

fish には var で値が設定されているため、これを割り当てて、新しい値を割り当てることができます。新しい値を aquarium に割り当てようとすると、val で定義されているため、エラーが発生します。

変数に格納する型は、コンパイラがコンテキストから判断できるタイミングです。コロンの表記を使用すると、いつでも変数の型を明示的に指定できます。

  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 ステートメントを 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 にすることはできません。

  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

fishFoodTreats」が「null」でない場合は省略し、使用します。それ以外の場合は、?: の後に値(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 で宣言されている変数は一度だけ割り当てることができます。
  • Kotlin 変数はデフォルトで null 許容ではありません。? を使用して変数を null 許容にします。
  • Kotlin では、for ループ内で配列のインデックスと要素を同時にループできます。

次の Kotlin プログラミング構成は、他の言語のものと同様です。

  • 配列とリストには、1 つの型または混合型を含めることができます。
  • 配列とリストはネストできます。
  • ループは 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 ブートキャンプ: コースへようこそをご覧ください。