Codelab ini adalah bagian dari kursus Kotlin Bootcamp for Programmers. Anda akan mendapatkan manfaat maksimal dari kursus ini jika menyelesaikan codelab secara berurutan. Anda mungkin dapat membaca cepat beberapa bagian, bergantung pada pengetahuan Anda. Kursus ini ditujukan bagi programer yang menguasai bahasa berorientasi objek, dan ingin mempelajari Kotlin.
Pengantar
Dalam codelab ini, Anda akan diperkenalkan dengan sejumlah fitur berguna di Kotlin, termasuk pasangan, koleksi, dan fungsi ekstensi.
Daripada membuat satu aplikasi contoh, pelajaran dalam kursus ini dirancang untuk membangun pengetahuan Anda, tetapi bersifat semi-independen satu sama lain sehingga Anda dapat membaca sekilas bagian yang sudah Anda kuasai. Untuk mengaitkannya, banyak contoh yang menggunakan tema akuarium. Jika Anda ingin melihat kisah akuarium selengkapnya, lihat kursus Kotlin Bootcamp for Programmers di Udacity.
Yang harus sudah Anda ketahui
- Sintaksis fungsi, class, dan metode Kotlin
- Cara menggunakan REPL (Read-Eval-Print Loop) Kotlin di IntelliJ IDEA
- Cara membuat class baru di IntelliJ IDEA dan menjalankan program
Yang akan Anda pelajari
- Cara menggunakan pasangan dan tiga rangkap
- Selengkapnya tentang koleksi
- Menentukan dan menggunakan konstanta
- Menulis fungsi ekstensi
Yang akan Anda lakukan
- Mempelajari pasangan, tiga rangkap, dan peta hash di REPL
- Mempelajari berbagai cara mengatur konstanta
- Menulis fungsi ekstensi dan properti ekstensi
Dalam tugas ini, Anda akan mempelajari pasangan dan tiga rangkap serta cara melakukan destrukturisasi. Pasangan dan rangkap tiga adalah class data siap pakai untuk 2 atau 3 item generik. Hal ini dapat berguna, misalnya, agar fungsi menampilkan lebih dari satu nilai.
Misalkan Anda memiliki List
ikan, dan fungsi isFreshWater()
untuk memeriksa apakah ikan tersebut adalah ikan air tawar atau ikan air asin. List.partition()
menampilkan dua daftar, satu dengan item yang kondisinya true
, dan yang lainnya untuk item yang kondisinya false
.
val twoLists = fish.partition { isFreshWater(it) }
println("freshwater: ${twoLists.first}")
println("saltwater: ${twoLists.second}")
Langkah 1: Buat beberapa pasangan dan tiga rangkai
- Buka REPL (Tools > Kotlin > Kotlin REPL).
- Buat pasangan, yang mengaitkan peralatan dengan penggunaannya, lalu cetak nilainya. Anda dapat membuat pasangan dengan membuat ekspresi yang menghubungkan dua nilai, seperti dua string, dengan kata kunci
to
, lalu menggunakan.first
atau.second
untuk merujuk ke setiap nilai.
val equipment = "fish net" to "catching fish"
println("${equipment.first} used for ${equipment.second}")
⇒ fish net used for catching fish
- Buat tiga tuple dan cetak dengan
toString()
, lalu konversikan ke daftar dengantoList()
. Anda membuat tiga rangkap menggunakanTriple()
dengan 3 nilai. Gunakan.first
,.second
, dan.third
untuk merujuk ke setiap nilai.
val numbers = Triple(6, 9, 42)
println(numbers.toString())
println(numbers.toList())
⇒ (6, 9, 42) [6, 9, 42]
Contoh di atas menggunakan jenis yang sama untuk semua bagian pasangan atau tiga bagian, tetapi hal itu tidak diperlukan. Bagian dapat berupa string, angka, atau daftar, misalnya—bahkan pasangan atau tiga bagian lainnya.
- Buat pasangan yang bagian pertama dari pasangan itu sendiri adalah pasangan.
val equipment2 = ("fish net" to "catching fish") to "equipment"
println("${equipment2.first} is ${equipment2.second}\n")
println("${equipment2.first.second}")
⇒ (fish net, catching fish) is equipment ⇒ catching fish
Langkah 2: Lakukan destrukturisasi beberapa pasangan dan tripel
Memisahkan pasangan dan tiga rangkap menjadi bagian-bagiannya disebut destrukturisasi. Tetapkan pasangan atau tiga angka ke jumlah variabel yang sesuai, dan Kotlin akan menetapkan nilai setiap bagian secara berurutan.
- Lakukan destrukturisasi pasangan dan cetak nilainya.
val equipment = "fish net" to "catching fish"
val (tool, use) = equipment
println("$tool is used for $use")
⇒ fish net is used for catching fish
- Mengurai tiga kali lipat dan mencetak nilai.
val numbers = Triple(6, 9, 42)
val (n1, n2, n3) = numbers
println("$n1 $n2 $n3")
⇒ 6 9 42
Perhatikan bahwa pasangan dan tiga kali dekonstruksi berfungsi sama seperti dengan class data, yang dibahas dalam codelab sebelumnya.
Dalam tugas ini, Anda akan mempelajari lebih lanjut koleksi, termasuk daftar, dan jenis koleksi baru, hash map.
Langkah 1: Pelajari lebih lanjut daftar
- Daftar dan daftar yang dapat diubah diperkenalkan dalam pelajaran sebelumnya. Struktur data ini sangat berguna, sehingga Kotlin menyediakan sejumlah fungsi bawaan untuk daftar. Tinjau daftar fungsi parsial ini untuk daftar. Anda dapat menemukan listingan lengkap di dokumentasi Kotlin untuk
List
danMutableList
.
Fungsi | Tujuan |
| Menambahkan item ke daftar yang dapat diubah. |
| Menghapus item dari daftar yang dapat berubah. |
| Menampilkan salinan daftar dengan elemen dalam urutan terbalik. |
| Menampilkan |
| Menampilkan bagian daftar, dari indeks pertama hingga, tetapi tidak termasuk, indeks kedua. |
- Masih bekerja di REPL, buat daftar angka dan panggil
sum()
di dalamnya. Ini menjumlahkan semua elemen.
val list = listOf(1, 5, 3, 4)
println(list.sum())
⇒ 13
- Buat daftar string dan jumlahkan daftar tersebut.
val list2 = listOf("a", "bbb", "cc")
println(list2.sum())
⇒ error: none of the following functions can be called with the arguments supplied:
- Jika elemen bukan sesuatu yang
List
tahu cara menjumlahkannya secara langsung, seperti string, Anda dapat menentukan cara menjumlahkannya menggunakan.sumBy()
dengan fungsi lambda, misalnya, untuk menjumlahkan berdasarkan panjang setiap string. Nama default untuk argumen lambda adalahit
dan di siniit
merujuk ke setiap elemen daftar saat daftar dilalui.
val list2 = listOf("a", "bbb", "cc")
println(list2.sumBy { it.length })
⇒ 6
- Ada banyak hal yang dapat Anda lakukan dengan daftar. Salah satu cara untuk melihat fungsi yang tersedia adalah dengan membuat daftar di IntelliJ IDEA, menambahkan titik, lalu melihat daftar pelengkapan otomatis di tooltip. Ini berfungsi untuk objek apa pun. Cobalah dengan daftar.
- Pilih
listIterator()
dari daftar, lalu buka daftar dengan pernyataanfor
dan cetak semua elemen yang dipisahkan dengan spasi.
val list2 = listOf("a", "bbb", "cc")
for (s in list2.listIterator()) {
println("$s ")
}
⇒ a bbb cc
Langkah 2: Coba peta hash
Di Kotlin, Anda dapat memetakan hampir semua hal ke hal lain menggunakan hashMapOf()
. Peta hash mirip dengan daftar pasangan, dengan nilai pertama bertindak sebagai kunci.
- Buat peta hash yang mencocokkan gejala, kunci, dan penyakit ikan, nilai.
val cures = hashMapOf("white spots" to "Ich", "red sores" to "hole disease")
- Kemudian, Anda dapat mengambil nilai penyakit berdasarkan kunci gejala, menggunakan
get()
, atau bahkan lebih singkat, tanda kurung siku[]
.
println(cures.get("white spots"))
⇒ Ich
println(cures["red sores"])
⇒ hole disease
- Coba tentukan gejala yang tidak ada di peta.
println(cures["scale loss"])
⇒ null
Jika kunci tidak ada dalam peta, mencoba menampilkan penyakit yang cocok akan menampilkan null
. Bergantung pada data peta, mungkin tidak ada kecocokan untuk kemungkinan kunci. Untuk kasus seperti itu, Kotlin menyediakan fungsi getOrDefault()
.
- Coba cari kunci yang tidak memiliki kecocokan, menggunakan
getOrDefault()
.
println(cures.getOrDefault("bloating", "sorry, I don't know"))
⇒ sorry, I don't know
Jika Anda perlu melakukan lebih dari sekadar menampilkan nilai, Kotlin menyediakan fungsi getOrElse()
.
- Ubah kode Anda agar menggunakan
getOrElse()
, bukangetOrDefault()
.
println(cures.getOrElse("bloating") {"No cure for this"})
⇒ No cure for this
Daripada menampilkan nilai default sederhana, kode apa pun yang berada di antara tanda kurung kurawal {}
akan dieksekusi. Dalam contoh, else
hanya menampilkan string, tetapi bisa juga berupa menemukan halaman web yang berisi solusi dan menampilkannya.
Sama seperti mutableListOf
, Anda juga dapat membuat mutableMapOf
. Peta yang dapat diubah memungkinkan Anda memasukkan dan menghapus item. Dapat diubah hanya berarti dapat berubah, tidak dapat diubah berarti tidak dapat berubah.
- Buat peta inventaris yang dapat diubah, yang memetakan string peralatan ke jumlah item. Buat dengan jaring ikan di dalamnya, lalu tambahkan 3 penggosok akuarium ke inventaris dengan
put()
, dan hapus jaring ikan denganremove()
.
val inventory = mutableMapOf("fish net" to 1)
inventory.put("tank scrubber", 3)
println(inventory.toString())
inventory.remove("fish net")
println(inventory.toString())
⇒ {fish net=1, tank scrubber=3}{tank scrubber=3}
Dalam tugas ini, Anda akan mempelajari konstanta di Kotlin dan berbagai cara untuk mengaturnya.
Langkah 1: Pelajari const vs. val
- Di REPL, coba buat konstanta numerik. Di Kotlin, Anda dapat membuat konstanta level teratas dan menetapkan nilai pada waktu kompilasi menggunakan
const val
.
const val rocks = 3
Nilai ditetapkan, dan tidak dapat diubah, yang sangat mirip dengan mendeklarasikan val
reguler. Jadi, apa perbedaan antara const val
dan val
? Nilai untuk const val
ditentukan pada waktu kompilasi, sedangkan nilai untuk val
ditentukan selama eksekusi program, yang berarti, val
dapat ditetapkan oleh fungsi saat runtime.
Artinya, val
dapat diberi nilai dari fungsi, tetapi const val
tidak dapat.
val value1 = complexFunctionCall() // OK
const val CONSTANT1 = complexFunctionCall() // NOT ok
Selain itu, const val
hanya berfungsi di tingkat teratas, dan di class singleton yang dideklarasikan dengan object
, bukan dengan class reguler. Anda dapat menggunakan ini untuk membuat file atau objek singleton yang hanya berisi konstanta, dan mengimpornya sesuai kebutuhan.
object Constants {
const val CONSTANT2 = "object constant"
}
val foo = Constants.CONSTANT2
Langkah 2: Buat objek pendamping
Kotlin tidak memiliki konsep konstanta tingkat class.
Untuk menentukan konstanta di dalam class, Anda harus membungkusnya ke dalam objek pendamping yang dideklarasikan dengan kata kunci companion
. Objek pendamping pada dasarnya adalah objek singleton dalam class.
- Buat class dengan objek pendamping yang berisi konstanta string.
class MyClass {
companion object {
const val CONSTANT3 = "constant in companion"
}
}
Perbedaan mendasar antara objek pendamping dan objek biasa adalah:
- Objek pendamping diinisialisasi dari konstruktor statis class yang memuatnya, yaitu dibuat saat objek dibuat.
- Objek reguler diinisialisasi secara lambat pada akses pertama ke objek tersebut; yaitu, saat pertama kali digunakan.
Ada lebih banyak hal yang perlu diketahui, tetapi untuk saat ini, Anda hanya perlu mengetahui cara membungkus konstanta dalam class di objek pendamping.
Dalam tugas ini, Anda akan mempelajari cara memperluas perilaku class. Menulis fungsi utilitas untuk memperluas perilaku class adalah hal yang sangat umum. Kotlin menyediakan sintaksis yang mudah untuk mendeklarasikan fungsi utilitas ini: fungsi ekstensi.
Fungsi ekstensi memungkinkan Anda menambahkan fungsi ke class yang sudah ada tanpa harus mengakses kode sumbernya. Misalnya, Anda dapat mendeklarasikannya dalam file Extensions.kt yang merupakan bagian dari paket Anda. Hal ini tidak benar-benar memodifikasi class, tetapi memungkinkan Anda menggunakan notasi titik saat memanggil fungsi pada objek class tersebut.
Langkah 1: Tulis fungsi ekstensi
- Masih bekerja di REPL, tulis fungsi ekstensi sederhana,
hasSpaces()
untuk memeriksa apakah string berisi spasi. Nama fungsi diawali dengan class yang mengoperasikannya. Di dalam fungsi,this
merujuk ke objek yang dipanggil, danit
merujuk ke iterator dalam panggilanfind()
.
fun String.hasSpaces(): Boolean {
val found = this.find { it == ' ' }
return found != null
}
println("Does it have spaces?".hasSpaces())
⇒ true
- Anda dapat menyederhanakan fungsi
hasSpaces()
.this
tidak diperlukan secara eksplisit, dan fungsi dapat direduksi menjadi satu ekspresi dan ditampilkan, sehingga tanda kurung kurawal{}
di sekitarnya juga tidak diperlukan.
fun String.hasSpaces() = find { it == ' ' } != null
Langkah 2: Pelajari batasan ekstensi
Fungsi ekstensi hanya memiliki akses ke API publik class yang diperluasnya. Variabel yang private
tidak dapat diakses.
- Coba tambahkan fungsi ekstensi ke properti yang ditandai
private
.
class AquariumPlant(val color: String, private val size: Int)
fun AquariumPlant.isRed() = color == "red" // OK
fun AquariumPlant.isBig() = size > 50 // gives error
⇒ error: cannot access 'size': it is private in 'AquariumPlant'
- Periksa kode di bawah dan cari tahu apa yang akan dicetak.
open class AquariumPlant(val color: String, private val size: Int)
class GreenLeafyPlant(size: Int) : AquariumPlant("green", size)
fun AquariumPlant.print() = println("AquariumPlant")
fun GreenLeafyPlant.print() = println("GreenLeafyPlant")
val plant = GreenLeafyPlant(size = 10)
plant.print()
println("\n")
val aquariumPlant: AquariumPlant = plant
aquariumPlant.print() // what will it print?
⇒ GreenLeafyPlant AquariumPlant
plant.print()
cetakan foto GreenLeafyPlant
. Anda mungkin berharap aquariumPlant.print()
juga mencetak GreenLeafyPlant
, karena telah diberi nilai plant
. Namun, jenisnya diselesaikan pada waktu kompilasi, sehingga AquariumPlant
dicetak.
Langkah 3: Tambahkan properti ekstensi
Selain fungsi ekstensi, Kotlin juga memungkinkan Anda menambahkan properti ekstensi. Seperti fungsi ekstensi, Anda menentukan class yang diperluas, diikuti dengan titik, lalu nama properti.
- Masih bekerja di REPL, tambahkan properti ekstensi
isGreen
keAquariumPlant
, yang merupakantrue
jika warnanya hijau.
val AquariumPlant.isGreen: Boolean
get() = color == "green"
Properti isGreen
dapat diakses seperti properti biasa; saat diakses, pengambil untuk isGreen
dipanggil untuk mendapatkan nilai.
- Cetak properti
isGreen
untuk variabelaquariumPlant
dan amati hasilnya.
aquariumPlant.isGreen
⇒ res4: kotlin.Boolean = true
Langkah 4: Ketahui penerima yang dapat bernilai null
Class yang Anda perluas disebut penerima, dan class tersebut dapat dibuat nullable. Jika Anda melakukannya, variabel this
yang digunakan dalam isi dapat berupa null
, jadi pastikan Anda mengujinya. Anda sebaiknya menggunakan penerima yang dapat bernilai null jika Anda memperkirakan pemanggil ingin memanggil metode ekstensi Anda pada variabel yang dapat bernilai null, atau jika Anda ingin memberikan perilaku default saat fungsi Anda diterapkan ke null
.
- Masih bekerja di REPL, tentukan metode
pull()
yang menggunakan penerima yang dapat bernilai null. Hal ini ditunjukkan dengan tanda tanya?
setelah jenis, sebelum titik. Di dalam isi, Anda dapat menguji apakahthis
bukannull
dengan menggunakan questionmark-dot-apply?.apply.
fun AquariumPlant?.pull() {
this?.apply {
println("removing $this")
}
}
val plant: AquariumPlant? = null
plant.pull()
- Dalam hal ini, tidak ada output saat Anda menjalankan program. Karena
plant
adalahnull
,println()
dalam tidak dipanggil.
Fungsi ekstensi sangat canggih, dan sebagian besar library standar Kotlin diimplementasikan sebagai fungsi ekstensi.
Dalam pelajaran ini, Anda telah mempelajari koleksi lebih lanjut, mempelajari konstanta, dan merasakan kekuatan fungsi dan properti ekstensi.
- Pasangan dan tiga rangkap dapat digunakan untuk menampilkan lebih dari satu nilai dari sebuah fungsi. Contoh:
val twoLists = fish.partition { isFreshWater(it) }
- Kotlin memiliki banyak fungsi berguna untuk
List
, sepertireversed()
,contains()
, dansubList()
. HashMap
dapat digunakan untuk memetakan kunci ke nilai. Contoh:val cures = hashMapOf("white spots" to "Ich", "red sores" to "hole disease")
- Deklarasikan konstanta waktu kompilasi menggunakan kata kunci
const
. Anda dapat menempatkannya di tingkat teratas, menyusunnya dalam objek singleton, atau menempatkannya dalam objek pendamping. - Objek pendamping adalah objek singleton dalam definisi class, yang ditentukan dengan kata kunci
companion
. - Fungsi dan properti ekstensi dapat menambahkan fungsi ke class. Contoh:
fun String.hasSpaces() = find { it == ' ' } != null
- Penerima yang dapat bernilai null memungkinkan Anda membuat ekstensi pada class yang dapat berupa
null
. Operator?.
dapat dipasangkan denganapply
untuk memeriksanull
sebelum menjalankan kode. Contoh:this?.apply { println("removing $this") }
Dokumentasi Kotlin
Jika Anda ingin mendapatkan informasi lebih lanjut tentang topik apa pun dalam kursus ini, atau jika Anda mengalami masalah, https://kotlinlang.org adalah titik awal terbaik Anda.
Tutorial Kotlin
Situs https://try.kotlinlang.org menyertakan tutorial lengkap yang disebut Kotlin Koans, interpreter berbasis web, dan serangkaian lengkap dokumentasi referensi dengan contoh.
Kursus Udacity
Untuk melihat kursus Udacity tentang topik ini, lihat Kotlin Bootcamp for Programmers.
IntelliJ IDEA
Dokumentasi untuk IntelliJ IDEA dapat ditemukan di situs JetBrains.
Bagian ini mencantumkan kemungkinan tugas pekerjaan rumah untuk siswa yang mengerjakan codelab ini sebagai bagian dari kursus yang dipimpin oleh instruktur. Instruktur menentukan hal berikut:
- Memberikan pekerjaan rumah jika diperlukan.
- Memberi tahu siswa cara mengirimkan tugas pekerjaan rumah.
- Memberi nilai tugas pekerjaan rumah.
Instruktur bisa menggunakan saran ini sesuai kebutuhan, dan bebas menugaskan pekerjaan rumah lain yang dirasa cocok.
Jika Anda menyelesaikan codelab ini sendiri, gunakan tugas pekerjaan rumah ini untuk menguji pengetahuan Anda.
Jawab pertanyaan-pertanyaan berikut
Pertanyaan 1
Manakah dari opsi berikut yang menampilkan salinan daftar?
▢ add()
▢ remove()
▢ reversed()
▢ contains()
Pertanyaan 2
Manakah dari fungsi ekstensi pada class AquariumPlant(val color: String, val size: Int, private val cost: Double, val leafy: Boolean)
ini yang akan memberikan error compiler?
▢ fun AquariumPlant.isRed() = color == "red"
▢ fun AquariumPlant.isBig() = size > 45
▢ fun AquariumPlant.isExpensive() = cost > 10.00
▢ fun AquariumPlant.isNotLeafy() = leafy == false
Pertanyaan 3
Manakah dari opsi berikut yang bukan tempat untuk menentukan konstanta dengan const val
?
▢ di tingkat teratas file
▢ di kelas reguler
▢ dalam objek singleton
▢ di objek pendamping
Lanjutkan ke pelajaran berikutnya:
Untuk ringkasan kursus, termasuk link ke codelab lainnya, lihat "Kotlin Bootcamp for Programmers: Welcome to the course".