Kotlin Bootcamp for Programmers 5.2: Generik

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 class, fungsi, dan metode generik, serta cara kerjanya di Kotlin.

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 membuat class baru di IntelliJ IDEA dan menjalankan program

Yang akan Anda pelajari

  • Cara menggunakan class, metode, dan fungsi generik

Yang akan Anda lakukan

  • Buat class generik dan tambahkan batasan
  • Membuat jenis in dan out
  • Membuat fungsi, metode, dan fungsi ekstensi generik

Pengantar generik

Kotlin, seperti banyak bahasa pemrograman, memiliki jenis generik. Jenis generik memungkinkan Anda membuat class generik, dan dengan demikian membuat class menjadi jauh lebih fleksibel.

Bayangkan Anda menerapkan class MyList yang menyimpan daftar item. Tanpa generik, Anda harus menerapkan versi baru MyList untuk setiap jenis: satu untuk Double, satu untuk String, satu untuk Fish. Dengan generik, Anda dapat membuat daftar generik, sehingga dapat menyimpan jenis objek apa pun. Ini seperti membuat jenis karakter pengganti yang akan cocok dengan banyak jenis.

Untuk menentukan jenis generik, masukkan T dalam tanda kurung sudut <T> setelah nama class. (Anda dapat menggunakan huruf lain atau nama yang lebih panjang, tetapi konvensi untuk jenis generik adalah T.)

class MyList<T> {
    fun get(pos: Int): T {
        TODO("implement")
    }
    fun addItem(item: T) {}
}

Anda dapat mereferensikan T seolah-olah itu adalah jenis normal. Jenis nilai yang ditampilkan untuk get() adalah T, dan parameter ke addItem() adalah jenis T. Tentu saja, daftar generik sangat berguna, sehingga class List dibuat ke dalam Kotlin.

Langkah 1: Buat hierarki huruf

Pada langkah ini, Anda akan membuat beberapa class untuk digunakan pada langkah berikutnya. Subclassing telah dibahas dalam codelab sebelumnya, tetapi berikut adalah tinjauan singkatnya.

  1. Agar contoh tidak terlalu rumit, buat paket baru di src dan beri nama generics.
  2. Dalam paket generics, buat file Aquarium.kt baru. Hal ini memungkinkan Anda mendefinisikan ulang sesuatu menggunakan nama yang sama tanpa konflik, sehingga kode lainnya untuk codelab ini masuk ke file ini.
  3. Buat hierarki jenis pasokan air. Mulai dengan membuat WaterSupply sebagai class open, sehingga dapat dibuatkan subclass-nya.
  4. Tambahkan parameter boolean var, needsProcessing. Tindakan ini akan otomatis membuat properti yang dapat diubah, beserta pengambil dan penyetel.
  5. Buat subclass TapWater yang memperluas WaterSupply, dan teruskan true untuk needsProcessing, karena air keran mengandung aditif yang buruk bagi ikan.
  6. Di TapWater, tentukan fungsi bernama addChemicalCleaners() yang menyetel needsProcessing ke false setelah membersihkan air. Properti needsProcessing dapat ditetapkan dari TapWater, karena secara default public dan dapat diakses oleh subclass. Berikut adalah kode yang sudah selesai.
package generics

open class WaterSupply(var needsProcessing: Boolean)

class TapWater : WaterSupply(true) {
   fun addChemicalCleaners() {
       needsProcessing = false
   }
}
  1. Buat dua subclass lagi dari WaterSupply, yang disebut FishStoreWater dan LakeWater. FishStoreWater tidak perlu diproses, tetapi LakeWater harus difilter dengan metode filter(). Setelah difilter, tidak perlu diproses lagi, jadi di filter(), tetapkan needsProcessing = false.
class FishStoreWater : WaterSupply(false)

class LakeWater : WaterSupply(true) {
   fun filter() {
       needsProcessing = false
   }
}

Jika Anda memerlukan informasi tambahan, tinjau pelajaran sebelumnya tentang pewarisan di Kotlin.

Langkah 2: Buat class generik

Pada langkah ini, Anda akan mengubah class Aquarium untuk mendukung berbagai jenis pasokan air.

  1. Di Aquarium.kt, tentukan class Aquarium, dengan <T> dalam tanda kurung setelah nama class.
  2. Tambahkan properti waterSupply yang tidak dapat diubah dari jenis T ke Aquarium.
class Aquarium<T>(val waterSupply: T)
  1. Tulis fungsi yang disebut genericsExample(). Hal ini bukan bagian dari class, sehingga dapat berada di tingkat teratas file, seperti fungsi main() atau definisi class. Dalam fungsi, buat Aquarium dan teruskan WaterSupply ke fungsi tersebut. Karena parameter waterSupply bersifat generik, Anda harus menentukan jenis dalam tanda kurung sudut <>.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
}
  1. Di genericsExample(), kode Anda dapat mengakses waterSupply akuarium. Karena berjenis TapWater, Anda dapat memanggil addChemicalCleaners() tanpa melakukan transmisi jenis.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Saat membuat objek Aquarium, Anda dapat menghapus tanda kurung sudut dan apa yang ada di antaranya karena Kotlin memiliki inferensi jenis. Jadi, tidak ada alasan untuk mengucapkan TapWater dua kali saat Anda membuat instance. Jenis dapat disimpulkan oleh argumen ke Aquarium; ini akan tetap membuat Aquarium berjenis TapWater.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Untuk melihat apa yang terjadi, cetak needsProcessing sebelum dan setelah memanggil addChemicalCleaners(). Berikut adalah fungsi yang telah selesai.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
    aquarium.waterSupply.addChemicalCleaners()
    println("water needs processing: ${aquarium.waterSupply.needsProcessing}")
}
  1. Tambahkan fungsi main() untuk memanggil genericsExample(), lalu jalankan program Anda dan amati hasilnya.
fun main() {
    genericsExample()
}
⇒ water needs processing: true
water needs processing: false

Langkah 3: Buat lebih spesifik

Umum berarti Anda dapat meneruskan hampir semua hal, dan terkadang hal itu menjadi masalah. Pada langkah ini, Anda akan membuat class Aquarium lebih spesifik tentang apa yang dapat Anda masukkan ke dalamnya.

  1. Di genericsExample(), buat Aquarium, teruskan string untuk waterSupply, lalu cetak properti waterSupply akuarium.
fun genericsExample() {
    val aquarium2 = Aquarium("string")
    println(aquarium2.waterSupply)
}
  1. Jalankan program Anda dan amati hasilnya.
⇒ string

Hasilnya adalah string yang Anda teruskan, karena Aquarium tidak membatasi T.Jenis apa pun, termasuk String, dapat diteruskan.

  1. Di genericsExample(), buat Aquarium lain, dengan meneruskan null untuk waterSupply. Jika waterSupply adalah null, cetak "waterSupply is null".
fun genericsExample() {
    val aquarium3 = Aquarium(null)
    if (aquarium3.waterSupply == null) {
        println("waterSupply is null")
    }
}
  1. Jalankan program Anda dan amati hasilnya.
⇒ waterSupply is null

Mengapa Anda dapat meneruskan null saat membuat Aquarium? Hal ini dapat dilakukan karena secara default, T adalah singkatan dari jenis Any? yang dapat bernilai null, jenis di bagian atas hierarki jenis. Berikut ini setara dengan yang Anda ketik sebelumnya.

class Aquarium<T: Any?>(val waterSupply: T)
  1. Agar tidak mengizinkan penerusan null, buat T berjenis Any secara eksplisit, dengan menghapus ? setelah Any.
class Aquarium<T: Any>(val waterSupply: T)

Dalam konteks ini, Any disebut batasan generik. Artinya, jenis apa pun dapat diteruskan untuk T selama bukan null.

  1. Yang Anda inginkan adalah memastikan bahwa hanya WaterSupply (atau salah satu subclass-nya) yang dapat diteruskan untuk T. Ganti Any dengan WaterSupply untuk menentukan batasan generik yang lebih spesifik.
class Aquarium<T: WaterSupply>(val waterSupply: T)

Langkah 4: Tambahkan pemeriksaan lainnya

Pada langkah ini, Anda akan mempelajari fungsi check() untuk membantu memastikan kode Anda berperilaku seperti yang diharapkan. Fungsi check() adalah fungsi library standar di Kotlin. Fungsi ini bertindak sebagai pernyataan dan akan memunculkan IllegalStateException jika argumennya bernilai false.

  1. Tambahkan metode addWater() ke class Aquarium untuk menambahkan air, dengan check() yang memastikan Anda tidak perlu memproses air terlebih dahulu.
class Aquarium<T: WaterSupply>(val waterSupply: T) {
    fun addWater() {
        check(!waterSupply.needsProcessing) { "water supply needs processing first" }
        println("adding water from $waterSupply")
    }    
}

Dalam hal ini, jika needsProcessing benar (true), check() akan menampilkan pengecualian.

  1. Di genericsExample(), tambahkan kode untuk membuat Aquarium dengan LakeWater, lalu tambahkan air ke dalamnya.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.addWater()
}
  1. Jalankan program Anda, dan Anda akan mendapatkan pengecualian, karena air perlu disaring terlebih dahulu.
⇒ Exception in thread "main" java.lang.IllegalStateException: water supply needs processing first
        at Aquarium.generics.Aquarium.addWater(Aquarium.kt:21)
  1. Tambahkan panggilan untuk menyaring air sebelum menambahkannya ke Aquarium. Sekarang, saat Anda menjalankan program, tidak ada pengecualian yang terjadi.
fun genericsExample() {
    val aquarium4 = Aquarium(LakeWater())
    aquarium4.waterSupply.filter()
    aquarium4.addWater()
}
⇒ adding water from generics.LakeWater@880ec60

Di atas mencakup dasar-dasar generik. Tugas berikut mencakup lebih banyak hal, tetapi konsep pentingnya adalah cara mendeklarasikan dan menggunakan class generik dengan batasan generik.

Dalam tugas ini, Anda akan mempelajari jenis in dan out dengan generik. Jenis in adalah jenis yang hanya dapat diteruskan ke class, bukan ditampilkan. Jenis out adalah jenis yang hanya dapat ditampilkan dari class.

Lihat class Aquarium dan Anda akan melihat bahwa jenis generik hanya ditampilkan saat mendapatkan properti waterSupply. Tidak ada metode yang menggunakan nilai berjenis T sebagai parameter (kecuali untuk menentukannya di konstruktor). Kotlin memungkinkan Anda menentukan jenis out untuk kasus ini, dan dapat menyimpulkan informasi tambahan tentang tempat jenis tersebut aman digunakan. Demikian pula, Anda dapat menentukan jenis in untuk jenis generik yang hanya diteruskan ke metode, bukan ditampilkan. Hal ini memungkinkan Kotlin melakukan pemeriksaan tambahan untuk keamanan kode.

Jenis in dan out adalah direktif untuk sistem jenis Kotlin. Menjelaskan seluruh sistem jenis berada di luar cakupan bootcamp ini (cukup rumit); namun, compiler akan menandai jenis yang tidak ditandai in dan out dengan tepat, jadi Anda perlu mengetahuinya.

Langkah 1: Tentukan jenis keluar

  1. Di class Aquarium, ubah T: WaterSupply menjadi jenis out.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    ...
}
  1. Dalam file yang sama, di luar class, deklarasikan fungsi addItemTo() yang mengharapkan Aquarium WaterSupply.
fun addItemTo(aquarium: Aquarium<WaterSupply>) = println("item added")
  1. Panggil addItemTo() dari genericsExample() dan jalankan program Anda.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    addItemTo(aquarium)
}
⇒ item added

Kotlin dapat memastikan bahwa addItemTo() tidak akan melakukan apa pun yang tidak aman jenisnya dengan WaterSupply generik, karena dideklarasikan sebagai jenis out.

  1. Jika Anda menghapus kata kunci out, compiler akan memberikan error saat memanggil addItemTo(), karena Kotlin tidak dapat memastikan bahwa Anda tidak melakukan hal yang tidak aman dengan jenis tersebut.

Langkah 2: Tentukan jenis in

Jenis in mirip dengan jenis out, tetapi untuk jenis generik yang hanya diteruskan ke fungsi, bukan ditampilkan. Jika Anda mencoba menampilkan jenis in, Anda akan mendapatkan error compiler. Dalam contoh ini, Anda akan menentukan jenis in sebagai bagian dari antarmuka.

  1. Di Aquarium.kt, tentukan antarmuka Cleaner yang menggunakan T generik yang dibatasi ke WaterSupply. Karena hanya digunakan sebagai argumen untuk clean(), Anda dapat menjadikannya parameter in.
interface Cleaner<in T: WaterSupply> {
    fun clean(waterSupply: T)
}
  1. Untuk menggunakan antarmuka Cleaner, buat class TapWaterCleaner yang mengimplementasikan Cleaner untuk membersihkan TapWater dengan menambahkan bahan kimia.
class TapWaterCleaner : Cleaner<TapWater> {
    override fun clean(waterSupply: TapWater) =   waterSupply.addChemicalCleaners()
}
  1. Di class Aquarium, perbarui addWater() untuk mengambil Cleaner jenis T, dan bersihkan air sebelum menambahkannya.
class Aquarium<out T: WaterSupply>(val waterSupply: T) {
    fun addWater(cleaner: Cleaner<T>) {
        if (waterSupply.needsProcessing) {
            cleaner.clean(waterSupply)
        }
        println("water added")
    }
}
  1. Perbarui kode contoh genericsExample() untuk membuat TapWaterCleaner, Aquarium dengan TapWater, lalu tambahkan air menggunakan pembersih. Robot ini akan menggunakan pembersih sesuai kebutuhan.
fun genericsExample() {
    val cleaner = TapWaterCleaner()
    val aquarium = Aquarium(TapWater())
    aquarium.addWater(cleaner)
}

Kotlin akan menggunakan informasi jenis in dan out untuk memastikan kode Anda menggunakan generik dengan aman. Out dan in mudah diingat: Jenis out dapat diteruskan ke luar sebagai nilai yang ditampilkan, jenis in dapat diteruskan ke dalam sebagai argumen.

Jika Anda ingin mempelajari lebih lanjut jenis masalah yang dapat diselesaikan oleh jenis dalam dan jenis luar, dokumentasi ini membahasnya secara mendalam.

Dalam tugas ini, Anda akan mempelajari fungsi generik dan kapan harus menggunakannya. Biasanya, membuat fungsi generik adalah ide yang baik setiap kali fungsi mengambil argumen class yang memiliki jenis generik.

Langkah 1: Buat fungsi generik

  1. Di generics/Aquarium.kt, buat fungsi isWaterClean() yang menggunakan Aquarium. Anda perlu menentukan jenis generik parameter; salah satu opsinya adalah menggunakan WaterSupply.
fun isWaterClean(aquarium: Aquarium<WaterSupply>) {
   println("aquarium water is clean: ${aquarium.waterSupply.needsProcessing}")
}

Namun, ini berarti Aquarium harus memiliki parameter jenis out agar dapat dipanggil. Terkadang out atau in terlalu membatasi karena Anda perlu menggunakan jenis untuk input dan output. Anda dapat menghapus persyaratan out dengan membuat fungsi generik.

  1. Untuk membuat fungsi generik, letakkan tanda kurung sudut setelah kata kunci fun dengan jenis generik T dan batasan apa pun, dalam hal ini, WaterSupply. Ubah Aquarium agar dibatasi oleh T, bukan oleh WaterSupply.
fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) {
   println("aquarium water is clean: ${!aquarium.waterSupply.needsProcessing}")
}

T adalah parameter jenis untuk isWaterClean() yang digunakan untuk menentukan jenis generik akuarium. Pola ini sangat umum, dan sebaiknya luangkan waktu untuk mempelajarinya.

  1. Panggil fungsi isWaterClean() dengan menentukan jenis dalam tanda kurung sudut tepat setelah nama fungsi dan sebelum tanda kurung.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean<TapWater>(aquarium)
}
  1. Karena inferensi jenis dari argumen aquarium, jenis tidak diperlukan, jadi hapus. Jalankan program Anda dan amati output-nya.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean(aquarium)
}
⇒ aquarium water is clean: false

Langkah 2: Buat metode generik dengan jenis yang di-reifikasi

Anda juga dapat menggunakan fungsi generik untuk metode, bahkan di class yang memiliki jenis generiknya sendiri. Pada langkah ini, Anda menambahkan metode generik ke Aquarium yang memeriksa apakah metode tersebut memiliki jenis WaterSupply.

  1. Di class Aquarium, deklarasikan metode, hasWaterSupplyOfType() yang menggunakan parameter generik R (T sudah digunakan) yang dibatasi ke WaterSupply, dan menampilkan true jika waterSupply berjenis R. Ini seperti fungsi yang Anda deklarasikan sebelumnya, tetapi di dalam class Aquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
  1. Perhatikan bahwa R terakhir digarisbawahi dengan warna merah. Arahkan kursor ke atasnya untuk melihat errornya.
  2. Untuk melakukan pemeriksaan is, Anda harus memberi tahu Kotlin bahwa jenisnya adalah reified, atau nyata, dan dapat digunakan dalam fungsi. Untuk melakukannya, letakkan inline di depan kata kunci fun, dan reified di depan jenis generik R.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R

Setelah jenis direifikasi, Anda dapat menggunakannya seperti jenis normal—karena merupakan jenis nyata setelah inline. Artinya, Anda dapat melakukan pemeriksaan is menggunakan jenis.

Jika Anda tidak menggunakan reified di sini, jenisnya tidak akan cukup "nyata" bagi Kotlin untuk mengizinkan pemeriksaan is. Hal ini karena jenis yang tidak direifikasi hanya tersedia pada waktu kompilasi, dan tidak dapat digunakan pada waktu runtime oleh program Anda. Hal ini dibahas lebih lanjut di bagian berikutnya.

  1. Teruskan TapWater sebagai jenisnya. Seperti memanggil fungsi generik, panggil metode generik dengan menggunakan tanda kurung sudut dengan jenis setelah nama fungsi. Jalankan program Anda dan amati hasilnya.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())   // true
}
⇒ true

Langkah 3: Buat fungsi ekstensi

Anda juga dapat menggunakan jenis yang di-reifikasi untuk fungsi reguler dan fungsi ekstensi.

  1. Di luar class Aquarium, tentukan fungsi ekstensi pada WaterSupply yang disebut isOfType() yang memeriksa apakah WaterSupply yang diteruskan berjenis tertentu, misalnya, TapWater.
inline fun <reified T: WaterSupply> WaterSupply.isOfType() = this is T
  1. Panggil fungsi ekstensi seperti metode.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.waterSupply.isOfType<TapWater>())  
}
⇒ true

Dengan fungsi ekstensi ini, tidak masalah jenis Aquarium (Aquarium atau TowerTank atau subkelas lainnya), asalkan merupakan Aquarium. Menggunakan sintaksis star-projection adalah cara mudah untuk menentukan berbagai kecocokan. Saat Anda menggunakan proyeksi bintang, Kotlin juga akan memastikan Anda tidak melakukan hal yang tidak aman.

  1. Untuk menggunakan proyeksi bintang, letakkan <*> setelah Aquarium. Pindahkan hasWaterSupplyOfType() menjadi fungsi ekstensi, karena sebenarnya bukan bagian dari API inti Aquarium.
inline fun <reified R: WaterSupply> Aquarium<*>.hasWaterSupplyOfType() = waterSupply is R
  1. Ubah panggilan menjadi hasWaterSupplyOfType() dan jalankan program Anda.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    println(aquarium.hasWaterSupplyOfType<TapWater>())
}
⇒ true

Pada contoh sebelumnya, Anda harus menandai jenis generik sebagai reified dan membuat fungsi inline, karena Kotlin perlu mengetahuinya saat runtime, bukan hanya saat waktu kompilasi.

Semua jenis generik hanya digunakan pada waktu kompilasi oleh Kotlin. Hal ini memungkinkan compiler memastikan bahwa Anda melakukan semuanya dengan aman. Saat runtime, semua jenis generik dihapus, sehingga muncul pesan error sebelumnya tentang pemeriksaan jenis yang dihapus.

Ternyata compiler dapat membuat kode yang benar tanpa menyimpan jenis generik hingga runtime. Namun, terkadang Anda melakukan sesuatu, seperti pemeriksaan is pada jenis generik, yang tidak dapat didukung oleh compiler. Itulah sebabnya Kotlin menambahkan jenis reified, atau nyata.

Anda dapat membaca selengkapnya tentang jenis yang di-reifikasi dan penghapusan jenis dalam dokumentasi Kotlin.

Pelajaran ini berfokus pada generik, yang penting untuk membuat kode lebih fleksibel dan lebih mudah digunakan kembali.

  • Buat class generik untuk membuat kode lebih fleksibel.
  • Tambahkan batasan generik untuk membatasi jenis yang digunakan dengan generik.
  • Gunakan jenis in dan out dengan generik untuk memberikan pemeriksaan jenis yang lebih baik guna membatasi jenis yang diteruskan ke atau ditampilkan dari class.
  • Buat fungsi dan metode generik untuk bekerja dengan jenis generik. Contoh:
    fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
  • Gunakan fungsi ekstensi generik untuk menambahkan fungsi non-inti ke class.
  • Jenis yang di-reifikasi terkadang diperlukan karena penghapusan jenis. Jenis yang di-reifikasi, tidak seperti jenis generik, tetap ada hingga runtime.
  • Gunakan fungsi check() untuk memverifikasi bahwa kode Anda berjalan seperti yang diharapkan. Contoh:
    check(!waterSupply.needsProcessing) { "water supply needs processing first" }

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 berikut

Pertanyaan 1

Manakah dari berikut ini yang merupakan konvensi untuk memberi nama jenis generik?

<Gen>

<Generic>

<T>

<X>

Pertanyaan 2

Pembatasan pada jenis yang diizinkan untuk jenis generik disebut:

▢ pembatasan umum

▢ batasan generik

▢ disambiguasi

▢ batas jenis generik

Pertanyaan 3

Direifikasi berarti:

▢ Dampak eksekusi sebenarnya dari suatu objek telah dihitung.

▢ Indeks entri terbatas telah ditetapkan pada class.

▢ Parameter jenis generik telah dibuat menjadi jenis nyata.

▢ Indikator error jarak jauh telah dipicu.

Lanjutkan ke pelajaran berikutnya: 6. Manipulasi fungsional

Untuk ringkasan kursus, termasuk link ke codelab lainnya, lihat "Kotlin Bootcamp for Programmers: Welcome to the course".