1. 始める前に
Kotlin プログラミングの基本を身につけたところで、今度は実践してみましょう。
この演習では、学習したコンセプトの理解度をテストします。実際のユースケースをテーマとしており、一部は以前に経験したことがあるかもしれません。
手順に沿って、各問題の解答を考えましょう。練習問題によっては、行き詰まった場合に役立つヒントが用意されています。解答コードは最後に掲載されていますが、演習に取り組んでから解答を確認することを強くおすすめします。
解答は問題を解決する方法の一つと捉え、自信を持って自由に試しましょう。一部の演習は複数の方法で解くことができます。また、関数と変数に異なる名前を使用できます。
自分のやりやすいペースで問題に取り組みましょう。時間が記載されていますが、これはあくまでも目安であり、遵守する必要はありません。必要なだけ時間をかけ、じっくりと問題に取り組んでください。
Kotlin のプレイグラウンドを使用して演習に取り組むことをおすすめします。
前提条件
- Kotlin のプレイグラウンドに慣れていること
- 関数の定義と呼び出しを行えること
- Kotlin の基本的なデータ型に関する知識があること
- 不変変数と可変変数に関する知識があること
println()
関数に関する知識があること- 初めての Kotlin プログラム、Kotlin で変数を作成して使用する、Kotlin で関数を作成して使用するの Codelab を完了していること
必要なもの
- ウェブブラウザがインストールされた、インターネットに接続できるパソコン
2. メッセージを出力する
このパスウェイで学習した内容を友人に伝えましょう。
- 次のようにメッセージを 4 行に分けて出力する
main()
関数を記述できますか。
Use the val keyword when the value doesn't change. Use the var keyword when the value can change. When you define a function, you define the parameters that can be passed to it. When you call a function, you pass arguments for the parameters.
3.コンパイル エラーを修正する
このプログラムは、友人からチャット メッセージを受信したことを通知するメッセージを出力します。
fun main() {
println("New chat message from a friend'}
}
- このプログラムでのコンパイル エラーの根本原因を特定し、修正できますか。
- このコードで、文字列と関数の引数の開閉を示す記号は適切に使用されていますか。
ヒント: コードを実行してコンパイル エラーを確認するために、Kotlin のプレイグラウンドを使用できます。
エラーを修正すると、プログラムはエラーなくコンパイルされ、次の出力が表示されるはずです。
New chat message from a friend
4. 文字列テンプレート
このプログラムは、特定の商品に予定されているプロモーション セールについてユーザーに通知します。文字列テンプレートがあり、割引率については discountPercentage
変数を使用し、セール対象商品については item
変数を使用しています。しかし、このコードではコンパイル エラーが発生します。
fun main() {
val discountPercentage: Int = 0
val offer: String = ""
val item = "Google Chromecast"
discountPercentage = 20
offer = "Sale - Up to $discountPercentage% discount on $item! Hurry up!"
println(offer)
}
- エラーの根本原因を特定し、修正できますか。
- Kotlin のプレイグラウンドでコードを実行する前に、このプログラムの出力を判断できますか。
ヒント: 読み取り専用の変数に値を再代入できますか。
エラーを修正すると、プログラムはエラーなくコンパイルされ、次の出力が表示されるはずです。
Sale - Up to 20% discount on Google Chromecast! Hurry up!
5. 文字列の連結
このプログラムは、パーティーの総人数を表示します。パーティーには大人と子供が出席しています。numberOfAdults
変数はパーティーの大人の人数を保持し、numberOfKids
変数は子供の人数を保持します。
fun main() {
val numberOfAdults = "20"
val numberOfKids = "30"
val total = numberOfAdults + numberOfKids
println("The total party size is: $total")
}
ステップ 1
- Kotlin のプレイグラウンドでコードを実行する前に、このプログラムの出力を判断できますか。
出力を判断したら、Kotlin のプレイグラウンドでコードを実行して表示された出力と一致するかどうかを確認します。
ヒント: 2 つの文字列に +
演算子を使用するとどうなりますか。
ステップ 2
このコードは機能して出力を生成しますが、出力にパーティー出席者の合計人数は表示されません。
- コードの問題点を見つけて、次の出力を行うように修正できますか。
The total party size is: 50
6. メッセージの書式設定
このプログラムは、ある従業員が今月受け取る給与の総額を表示します。給与の総額は、ある従業員が毎月受け取る額の baseSalary
変数と、その従業員に追加で支給されるボーナスの bonusAmount
変数という、2 つの部分に分かれています。
fun main() {
val baseSalary = 5000
val bonusAmount = 1000
val totalSalary = "$baseSalary + $bonusAmount"
println("Congratulations for your bonus! You will receive a total of $totalSalary (additional bonus).")
}
- このコードを Kotlin のプレイグラウンドで実行する前に、出力を把握できますか。
- コードを Kotlin のプレイグラウンドで実行すると、想定どおりの出力が表示されますか。
7. 基本的な数学演算を実装する
この演習では、基本的な数学演算を行って出力を表示するプログラムを作成します。
ステップ 1
この main()
関数ではコンパイル エラーが 1 つ発生します。
fun main() {
val firstNumber = 10
val secondNumber = 5
println("$firstNumber + $secondNumber = $result")
}
- プログラムが次の出力を表示するようにエラーを修正できますか。
10 + 5 = 15
ステップ 2
このコードは機能しますが、2 つの数を加算するロジックは result 変数内にあるため、コードを柔軟に再利用しにくくなっています。代わりに、加算演算を add()
関数に抽出してコードを再利用できるようにします。そのために、コードを次のように更新します。なお、このコードでは thirdNumber
という新しい val
を導入し、この新しい変数の結果を firstNumber
で出力します。
fun main() {
val firstNumber = 10
val secondNumber = 5
val thirdNumber = 8
val result = add(firstNumber, secondNumber)
val anotherResult = add(firstNumber, thirdNumber)
println("$firstNumber + $secondNumber = $result")
println("$firstNumber + $thirdNumber = $anotherResult")
}
// Define add() function below this line
- プログラムが次の出力を表示するように
add()
関数を定義できますか。
10 + 5 = 15 10 + 8 = 18
ステップ 3
これで、2 つの数を加算する再利用可能な関数ができました。
add()
関数を実装したときと同様にsubtract()
関数を実装できますか。subtract()
関数を使用するようにmain()
関数も変更し、想定どおりに動作することを確認します。
ヒント: 加算、減算、その他の数学演算の違いを考えてください。そこから解答コードに取り組みましょう。
8. デフォルトのパラメータ
Gmail には、新しいデバイスでログインが試行されるたびにユーザーに通知を送信する機能があります。
この演習では、このメッセージ テンプレートを使用してユーザーにメッセージを表示するプログラムを作成します。
There's a new sign-in request on operatingSystem for your Google Account emailId.
operatingSystem
パラメータと emailId
パラメータを受け取り、指定された形式でメッセージを作成してそのメッセージを返す関数を実装する必要があります。
たとえば、operatingSystem
に「Chrome OS
」、emailId
に「sample@gmail.com
」を指定して関数を呼び出した場合、次の文字列が返されます。
There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.
ステップ 1
- このプログラムが出力を表示するように
displayAlertMessage()
関数を実装できますか。
fun main() {
val operatingSystem = "Chrome OS"
val emailId = "sample@gmail.com"
println(displayAlertMessage(operatingSystem, emailId))
}
// Define your displayAlertMessage() below this line.
- プログラムが次の出力を表示しますか。
There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.
ステップ 2
これでメッセージを表示できました。ただし、場合によってはユーザーのオペレーティング システムを特定できないことがあります。そのような場合は、オペレーティング システム名を Unknown OS
として指定する必要があります。関数を呼び出すたびに Unknown OS
引数を渡す必要がなくなるよう、コードをさらに最適化できます。
- この情報で、次の出力を表示するようにコードを最適化する方法がわかりますか。
There's a new sign-in request on Unknown OS for your Google Account user_one@gmail.com. There's a new sign-in request on Windows for your Google Account user_two@gmail.com. There's a new sign-in request on Mac OS for your Google Account user_three@gmail.com.
- 上記のメッセージを出力するには、
main()
関数の実装を次のように置き換えます。
fun main() {
val firstUserEmailId = "user_one@gmail.com"
// The following line of code assumes that you named your parameter as emailId.
// If you named it differently, feel free to update the name.
println(displayAlertMessage(emailId = firstUserEmailId))
println()
val secondUserOperatingSystem = "Windows"
val secondUserEmailId = "user_two@gmail.com"
println(displayAlertMessage(secondUserOperatingSystem, secondUserEmailId))
println()
val thirdUserOperatingSystem = "Mac OS"
val thirdUserEmailId = "user_three@gmail.com"
println(displayAlertMessage(thirdUserOperatingSystem, thirdUserEmailId))
println()
}
9. 歩数計
歩数計は、歩数をカウントする電子デバイスです。現在では、ほぼすべてのスマートフォン、スマートウォッチ、フィットネス機器に歩数計が内蔵されています。健康&フィットネス アプリは、内蔵の歩数計を使用して歩数を計算します。この関数はユーザーの歩数に基づいて消費カロリー数を計算します。
- ベスト プラクティスに基づいて、このプログラムの関数、関数パラメータ、変数の名前を変更できますか。
fun main() {
val Steps = 4000
val caloriesBurned = PEDOMETERstepsTOcalories(Steps);
println("Walking $Steps steps burns $caloriesBurned calories")
}
fun PEDOMETERstepsTOcalories(NumberOFStepS: Int): Double {
val CaloriesBURNEDforEachStep = 0.04
val TotalCALORIESburned = NumberOFStepS * CaloriesBURNEDforEachStep
return TotalCALORIESburned
}
10. 2 つの数を比較する
最新のスマートフォンには、利用時間(1 日にスマートフォンに費やした時間)を記録する機能が組み込まれています。
この演習では、今日スマートフォンに費やした時間(分単位)と昨日費やした時間を比較する関数を実装します。この関数は 2 つの整数パラメータを受け入れ、ブール値を返します。
最初のパラメータは今日費やした時間(分単位)、2 番目のパラメータは昨日費やした時間(分単位)です。この関数は、昨日より今日の方がスマートフォンに費やした時間が多い場合に true
値を返します。そうでない場合は false
値を返します。
たとえば、次の名前付き引数で関数を呼び出したとします。
timeSpentToday = 300
とtimeSpentYesterday = 250
の場合、関数はtrue
値を返します。timeSpentToday = 300
とtimeSpentYesterday = 300
の場合、関数はfalse
値を返します。timeSpentToday = 200
とtimeSpentYesterday = 220
の場合、関数はfalse
値を返します。
ヒント: >
比較演算子は、演算子の前の値が後の値より大きい場合、true
値を返します。そうでない場合は false
値を返します。
11. 重複するコードを関数に移動する
このプログラムはさまざまな都市の天気を表示します。これには、都市名、その日の最高気温と最低気温、降水確率が含まれます。
fun main() {
println("City: Ankara")
println("Low temperature: 27, High temperature: 31")
println("Chance of rain: 82%")
println()
println("City: Tokyo")
println("Low temperature: 32, High temperature: 36")
println("Chance of rain: 10%")
println()
println("City: Cape Town")
println("Low temperature: 59, High temperature: 64")
println("Chance of rain: 2%")
println()
println("City: Guatemala City")
println("Low temperature: 50, High temperature: 55")
println("Chance of rain: 7%")
println()
}
各都市の天気を表示するコードには多くの類似点があります。たとえば、"City:"
や "Low temperature:"
のように何度も繰り返されるフレーズがあります。類似したコードが繰り返されると、プログラムでエラーが発生するリスクが生じます。いずれかの都市について、タイプミスをしたり、天気の詳細情報を 1 つ忘れたりするかもしれません。
main()
関数の繰り返しを減らすために、1 つの都市について天気の詳細情報を表示する関数を作成し、残りの都市についても同様にできますか。- 都市ごとに作成した関数を呼び出し、適切な天気の詳細情報を引数として渡すように
main()
関数を更新できますか。
12. 解答コード
メッセージを出力する
解答は、println()
関数を使用して各行でメッセージを出力します。
fun main() {
println("Use the val keyword when the value doesn't change.")
println("Use the var keyword when the value can change.")
println("When you define a function, you define the parameters that can be passed to it.")
println("When you call a function, you pass arguments for the parameters.")
}
コンパイル エラーを修正する
コードにはコンパイル エラーが 2 つ含まれていました。
- 文字列は、一重引用符ではなく二重引用符で終わる必要があります。
- 関数の引数は、中かっこではなく丸かっこで囲む必要があります。
fun main() {
println("New chat message from a friend")
}
文字列テンプレート
読み取り専用変数の discountPercentage
と offer
を新しい値に代入すると、コンパイル エラーが起きます。このような代入は認められていません。
fun main() {
val discountPercentage = 20
val item = "Google Chromecast"
val offer = "Sale - Up to $discountPercentage% discount off $item! Hurry Up!"
println(offer)
}
代替策として、var
キーワードを使用して discountPercentage
整数と offer
文字列を宣言します。ただし、これらの値はプログラムのコンテキストでは不変であるため、val
キーワードのままで問題ありません。
文字列の連結
ステップ 1
プログラムは次の出力を表示します。
The total party size is: 2030
これはひっかけ問題でした。+
演算子を String
値に使用すると、連結された文字列が生成されます。整数が二重引用符で囲まれているため、整数ではなく文字列として扱われ、2030
という出力になります。
ステップ 2
numberOfAdults
変数と numberOfKids
変数を囲んでいる二重引用符を削除して Int
変数に変換します。
fun main() {
val numberOfAdults = 20
val numberOfKids = 30
val total = numberOfAdults + numberOfKids
println("The total party size is: $total")
}
Kotlin コンパイラは代入された値に基づいて変数の型を推定できる、ということを覚えているでしょうか。この場合、コンパイラは numberOfAdults
変数と numberOfKids
変数が Int
型であると推定します。
メッセージの書式設定
プログラムは次の出力を表示します。
Congratulations for your bonus! You will receive a total of 5000 + 1000 (additional bonus).
"$baseSalary + $bonusAmount"
は、テンプレート式の構文を使用しています。テンプレート式では、まずコードが評価され、その結果が文字列として連結されます。
この問題では、$baseSalary
変数の値が 5000
と評価され、$bonusAmount
変数の値が 1000
と評価されます。次に、結果が連結されて "5000 + 1000"
となり、result
変数に代入されます。
基本的な数学演算を実装する
ステップ 1
val
キーワードで不変の result
変数を定義してから、加算演算の結果を代入します。
fun main() {
val firstNumber = 10
val secondNumber = 5
val result = firstNumber + secondNumber
println("$firstNumber + $secondNumber = $result")
}
ステップ 2
firstNumber
パラメータとsecondNumber
パラメータ(どちらもInt
型)を受け取りInt
値を返すadd()
関数を作成します。add()
関数の本文に加算演算のコードを入力し、return
キーワードを使用して演算の結果を返します。
fun add(firstNumber: Int, secondNumber: Int): Int {
return firstNumber + secondNumber
}
ステップ 3
firstNumber
パラメータとsecondNumber
パラメータ(どちらもInt
型)を受け取りInt
値を返すsubtract()
関数を定義します。subtract()
関数の本文に減算演算のコードを入力し、return
キーワードを使用して演算の結果を返します。
fun subtract(firstNumber: Int, secondNumber: Int): Int {
return firstNumber - secondNumber
}
- 新しい
subtract()
関数を使用するようにmain()
関数を変更します。解答例を以下に示します。
fun main() {
val firstNumber = 10
val secondNumber = 5
val thirdNumber = 8
val result = add(firstNumber, secondNumber)
val anotherResult = subtract(firstNumber, thirdNumber)
println("$firstNumber + $secondNumber = $result")
println("$firstNumber - $thirdNumber = $anotherResult")
}
fun add(firstNumber: Int, secondNumber: Int): Int {
return firstNumber + secondNumber
}
fun subtract(firstNumber: Int, secondNumber: Int): Int {
return firstNumber - secondNumber
}
デフォルトのパラメータ
ステップ 1
operatingSystem
パラメータとemailId
パラメータ(どちらもString
型)を受け取りString
値を返すdisplayAlertMessage()
関数を作成します。- 関数の本文で、テンプレート式を使用してメッセージを更新し、返します。
fun displayAlertMessage(operatingSystem: String, emailId: String): String {
return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}
ステップ 2
operatingSystem
パラメータに"Unknown OS"
値を代入します。
fun displayAlertMessage(
operatingSystem: String = "Unknown OS",
emailId: String
): String {
return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}
歩数計
関数名と変数名はキャメルケースの命名規則に従って付ける必要があります。
名前に複数の単語が含まれている場合は、最初の単語の最初の文字を小文字にし、後続の単語の最初の文字を大文字にして、単語間のスペースをすべて削除します。
関数名の例:
calculateTip
displayMessage
takePhoto
変数名の例:
numberOfEmails
cityName
bookPublicationDate
名前の詳細については、命名ルールをご覧ください。
Kotlin キーワードは、Kotlin 言語ですでに特定の意味が割り当てられているため、関数名として使用しないでください。
解答コードは次のコード スニペットのようになります。
fun main() {
val steps = 4000
val caloriesBurned = pedometerStepsToCalories(steps);
println("Walking $steps steps burns $caloriesBurned calories")
}
fun pedometerStepsToCalories(numberOfSteps: Int): Double {
val caloriesBurnedForEachStep = 0.04
val totalCaloriesBurned = numberOfSteps * caloriesBurnedForEachStep
return totalCaloriesBurned
}
2 つの数を比較する
timeSpentToday
パラメータとtimeSpentYesterday
パラメータ(どちらもInt
型)を受け取りBoolean
値を返すcompareTime()
関数を作成します。
解答では >
比較演算子を使用します。この演算子は Boolean
値として評価されるため、compareTime()
関数は単に timeSpentToday > timeSpentYesterday
の結果を返します。
たとえば、300
引数を timeSpentToday
パラメータに渡し、250
引数を timeSpentYesterday
パラメータに渡すと、関数の本文は 300 > 250
と評価され、300 は 250 より大きいため true
値が返されます。
fun main() {
println("Have I spent more time using my phone today: ${compareTime(300, 250)}")
println("Have I spent more time using my phone today: ${compareTime(300, 300)}")
println("Have I spent more time using my phone today: ${compareTime(200, 220)}")
}
fun compareTime(timeSpentToday: Int, timeSpentYesterday: Int): Boolean {
return timeSpentToday > timeSpentYesterday
}
Have I spent more time using my phone today: true Have I spent more time using my phone today: false Have I spent more time using my phone today: false
重複するコードを関数に移動する
main()
関数の後に、アンカラ市の天気の詳細情報を表示する関数を作成します。
関数名には、printWeatherForCity()
などを使用できます。
- この関数を
main()
関数から呼び出します。
プログラムはアンカラの天気の詳細情報を表示します。
fun main() {
printWeatherForCity()
}
fun printWeatherForCity() {
println("City: Ankara")
println("Low temperature: 27, High temperature: 31")
println("Chance of rain: 82%")
println()
}
これで、他の都市における天気の詳細情報を表示できる、柔軟性の高い別の関数を作成できるようになりました。
println()
ステートメントのアンカラ固有の部分を変数に置き換えます。
変数名にはキャメルケースの命名規則を使用し、変数の前に $
記号を付けて、変数名の代わりに変数の値が使用されるようにしてください。これらは以前の Codelab で学習した文字列テンプレートです。
fun printWeatherForCity() {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- これらの変数が、関数が呼び出されたときに必ず渡されるパラメータとなるように関数の定義を変更し、各パラメータのデータ型を指定します。
cityName
パラメータは String
型ですが、lowTemp
、highTemp
、chanceOfRain
パラメータは Int
型です。
メッセージは出力に表示されるため、関数の定義に return
値は必要ありません。
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
printWeatherForCity()
関数を呼び出してアンカラの天気の詳細情報を渡すように、main()
関数を更新します。
都市名は "Ankara"
、最低気温は 27
、最高気温は 31
、降水確率は 82
です。
fun main() {
printWeatherForCity("Ankara", 27, 31, 82)
}
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- プログラムを実行し、出力にアンカラの天気の詳細情報が表示されることを確認します。
- 他の都市における天気の詳細情報を指定して
printWeatherForCity()
関数を呼び出します。
fun main() {
printWeatherForCity("Ankara", 27, 31, 82)
printWeatherForCity("Tokyo", 32, 36, 10)
printWeatherForCity("Cape Town", 59, 64, 2)
printWeatherForCity("Guatemala City", 50, 55, 7)
}
fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
println("City: $cityName")
println("Low temperature: $lowTemp, High temperature: $highTemp")
println("Chance of rain: $chanceOfRain%")
println()
}
- プログラムを実行します。
元のプログラムと同じ出力が表示されますが、コードが簡潔になり、不要な繰り返しが含まれなくなりました。都市の天気の詳細情報を出力するコードはすべて、printWeatherForCity()
関数という 1 か所に集約されています。天気の詳細情報の表示方法を変更する場合は、1 か所で変更してすべての都市に適用できます。
13. その他の演習
Kotlin 言語に関するその他の演習については、JetBrains Academy の Kotlin 基本トラックをご覧ください。特定のトピックに移動するには、ナレッジマップに移動して、このトラックで扱っているトピックの一覧を確認してください。