Bootcamp Kotlin untuk Programmer 5.2: Generik

Codelab ini adalah bagian dari kursus Bootcamp Kotlin untuk Programer. Anda akan mendapatkan manfaat maksimal dari kursus ini jika Anda mengerjakan 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 ke class, fungsi, dan metode generik, serta cara kerjanya di Kotlin.

Daripada membuat aplikasi sampel tunggal, pelajaran dalam kursus ini didesain untuk membangun pengetahuan Anda, tetapi bersifat semi-mandiri, sehingga Anda dapat membaca cepat bagian yang sudah Anda pahami. Untuk menyatukannya, banyak contoh menggunakan tema akuarium. Dan jika Anda ingin melihat cerita lengkap akuarium, lihat kursus Udacity Kotlin Bootcamp for Programmers.

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

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

Pengantar generik

Kotlin, seperti banyak bahasa pemrograman, memiliki jenis generik. Tipe generik memungkinkan Anda membuat kelas generik, sehingga membuat kelas jauh lebih fleksibel.

Bayangkan Anda mengimplementasikan class MyList yang menyimpan daftar item. Tanpa generik, Anda harus mengimplementasikan versi baru MyList untuk setiap jenis: satu untuk Double, satu untuk String, satu untuk Fish. Dengan generik, Anda bisa membuat daftar generik, sehingga bisa menampung segala jenis objek. Hal ini seperti membuat jenis karakter pengganti yang akan cocok dengan banyak jenis.

Untuk menentukan jenis generik, letakkan T dalam tanda kurung sudut <T> setelah nama class. (Anda dapat menggunakan huruf lain atau nama yang lebih panjang, tetapi konvensi untuk jenis umum 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 di-build ke dalam Kotlin.

Langkah 1: Buat hierarki jenis

Pada langkah ini, Anda membuat beberapa class untuk digunakan di langkah berikutnya. Subclass tercakup dalam codelab sebelumnya, tetapi berikut adalah ulasan singkatnya.

  1. Agar contoh tetap ringkas, buat paket baru di bagian src dan beri nama generics.
  2. Dalam paket generik, buat file Aquarium.kt baru. Hal ini memungkinkan Anda untuk menentukan ulang sesuatu menggunakan nama yang sama tanpa konflik, sehingga sisa kode untuk codelab ini akan dimasukkan ke file ini.
  3. Membuat hierarki jenis jenis pasokan air. Mulai dengan membuat WaterSupply sebagai class open sehingga dapat dibuat subclass.
  4. Tambahkan parameter var boolean, needsProcessing. Tindakan ini akan otomatis membuat properti yang dapat berubah, beserta pengambil dan penyetel.
  5. Buat subclass TapWater yang memperluas WaterSupply, dan meneruskan true untuk needsProcessing, karena air keran berisi aditif yang buruk bagi ikan.
  6. Di TapWater, tentukan fungsi bernama addChemicalCleaners() yang menetapkan needsProcessing ke false setelah membersihkan air. Properti needsProcessing dapat disetel dari TapWater, karena properti tersebut public secara default 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 WaterSupply lainnya, bernama FishStoreWater dan LakeWater. FishStoreWater tidak perlu diproses, tetapi LakeWater harus difilter dengan metode filter(). Setelah difilter, file 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 tutorial 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 yang tidak dapat diubah waterSupply dari jenis T ke Aquarium.
class Aquarium<T>(val waterSupply: T)
  1. Tulis fungsi yang disebut genericsExample(). Ini bukan bagian dari class, sehingga dapat berada di tingkat atas file, seperti fungsi main() atau definisi class. Dalam fungsi, buat Aquarium dan teruskan WaterSupply. Karena parameter waterSupply bersifat umum, Anda harus menentukan jenis dalam tanda kurung sudut <>.
fun genericsExample() {
    val aquarium = Aquarium<TapWater>(TapWater())
}
  1. Dalam genericsExample(), kode Anda dapat mengakses waterSupply akuarium. Karena jenisnya TapWater, Anda dapat memanggil addChemicalCleaners() tanpa transmisi jenis apa pun.
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 dengan argumen ke Aquarium; jenis tersebut tetap akan membuat Aquarium dari jenis TapWater.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    aquarium.waterSupply.addChemicalCleaners()
}
  1. Untuk melihat apa yang terjadi, cetak needsProcessing sebelum dan sesudah 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

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

  1. Di genericsExample(), buat Aquarium, dengan meneruskan 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 memberikan batasan apa pun pada T.Jenis apa pun, termasuk String, yang 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 dimungkinkan karena secara default T adalah singkatan dari jenis nullable Any?, yaitu jenis di bagian atas hierarki jenis. Berikut ini sama dengan yang Anda ketik sebelumnya.

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

Dalam konteks ini, Any disebut batasan umum. Ini berarti jenis apa pun dapat diteruskan untuk T selama bukan null.

  1. Yang benar-benar Anda inginkan adalah memastikan bahwa hanya WaterSupply (atau salah satu subclass-nya) yang dapat diteruskan untuk T. Mengganti Any dengan WaterSupply untuk menentukan batasan umum 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 berfungsi 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, check() akan memunculkan 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, lalu Anda akan mendapatkan pengecualian karena air harus difilter 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 memfilter air sebelum menambahkannya ke Aquarium. Sekarang, ketika Anda menjalankan program, tidak ada pengecualian yang ditampilkan.
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, tetapi konsep pentingnya adalah cara mendeklarasikan dan menggunakan class generik dengan batasan umum.

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

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

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

Langkah 1: Menentukan 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 dari 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 jenis apa pun yang tidak aman dengan WaterSupply generik, karena dideklarasikan sebagai jenis out.

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

Langkah 2: Tentukan in-type

Jenis in mirip dengan jenis out, tetapi untuk jenis umum yang hanya pernah diteruskan ke fungsi, tidak ditampilkan. Jika mencoba menampilkan jenis in, Anda akan mengalami 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 untuk WaterSupply. Karena metode ini hanya digunakan sebagai argumen untuk clean(), Anda dapat menjadikannya sebagai parameter in.
interface Cleaner<in T: WaterSupply> {
    fun clean(waterSupply: T)
}
  1. Untuk menggunakan antarmuka Cleaner, buat class TapWaterCleaner yang menerapkan 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 dari 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. Alat 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 sebagai nilai hasil, jenis in dapat diteruskan ke dalam sebagai argumen.

Jika Anda ingin menggali lebih dalam tentang masalah jenis dan jenis penyelesaian, dokumentasi ini membahasnya secara mendalam.

Dalam tugas ini, Anda akan mempelajari fungsi generik dan kapan menggunakannya. Biasanya, membuat fungsi generik sebaiknya dilakukan setiap kali fungsi mengambil argumen dari class yang memiliki jenis generik.

Langkah 1: Buat fungsi umum

  1. Di generics/Aquarium.kt, buat fungsi isWaterClean() yang menggunakan Aquarium. Anda perlu menentukan jenis umum parameter; satu opsi 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 ketat karena Anda harus menggunakan jenis untuk input dan output. Anda dapat menghapus persyaratan out dengan membuat fungsi bersifat umum.

  1. Untuk membuat fungsi menjadi generik, letakkan tanda kurung sudut setelah kata kunci fun dengan jenis umum 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 ada baiknya Anda meluangkan waktu sejenak untuk mengerjakan hal ini.

  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 ini tidak diperlukan, jadi hapus jenis tersebut. Jalankan program Anda dan amati outputnya.
fun genericsExample() {
    val aquarium = Aquarium(TapWater())
    isWaterClean(aquarium)
}
⇒ aquarium water is clean: false

Langkah 2: Buat metode generik dengan jenis reified

Anda juga dapat menggunakan fungsi generik untuk metode, bahkan di class yang memiliki jenis generik 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 umum R (T sudah digunakan) yang dibatasi ke WaterSupply, dan tampilkan true jika waterSupply adalah jenis R. Ini mirip dengan fungsi yang Anda deklarasikan sebelumnya, tetapi di dalam class Aquarium.
fun <R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R
  1. Perhatikan bahwa R akhir digarisbawahi dengan warna merah. Arahkan pointer ke atasnya untuk melihat error yang terjadi.
  2. Untuk melakukan pemeriksaan is, Anda harus memberi tahu Kotlin bahwa jenisnya ditetapkan, atau nyata, dan dapat digunakan dalam fungsi. Untuk melakukannya, tempatkan inline di depan kata kunci fun dan reified di depan jenis generik R.
inline fun <reified R: WaterSupply> hasWaterSupplyOfType() = waterSupply is R

Setelah jenis diperbaiki, Anda dapat menggunakannya seperti jenis normal—karena ini adalah jenis nyata setelah inline. Artinya, Anda dapat melakukan pemeriksaan is menggunakan jenisnya.

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

  1. Meneruskan TapWater sebagai jenis. Seperti memanggil fungsi generik, panggil metode generik dengan menggunakan tanda kurung sudut dengan tipe 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 reified untuk fungsi reguler dan fungsi ekstensi.

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

Dengan fungsi ekstensi ini, jenis Aquarium apa pun (Aquarium atau TowerTank atau beberapa subclass lainnya) tidak masalah, asalkan itu adalah Aquarium. Menggunakan sintaksis bintang-proyeksi adalah cara yang mudah untuk menentukan berbagai kecocokan. Dan saat Anda menggunakan proyeksi bintang, Kotlin juga akan memastikan Anda tidak melakukan hal tidak aman.

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

Pada contoh sebelumnya, Anda harus menandai jenis umum sebagai reified dan membuat fungsi inline, karena Kotlin perlu mengetahuinya saat runtime, bukan hanya 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 akan dihapus, sehingga pesan error sebelumnya tentang memeriksa jenis yang dihapus akan dihapus.

Ternyata compiler dapat membuat kode yang tepat tanpa menyimpan tipe generik hingga runtime. Namun, ini berarti bahwa terkadang Anda melakukan sesuatu, seperti is memeriksa jenis umum, yang tidak dapat didukung oleh compiler. Itulah sebabnya Kotlin menambahkan jenis yang nyata atau nyata.

Anda dapat membaca selengkapnya tentang jenis yang diperbaiki dan penghapusan jenis di dokumentasi Kotlin.

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

  • Membuat class generik untuk membuat kode lebih fleksibel.
  • Tambahkan batasan umum 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 digunakan dengan jenis generik. Contoh:
    fun <T: WaterSupply> isWaterClean(aquarium: Aquarium<T>) { ... }
  • Gunakan fungsi ekstensi generik untuk menambahkan fungsi non-inti ke class.
  • Jenis reifikasi terkadang diperlukan karena penghapusan jenis. Tidak seperti jenis generik, jenis reified akan terus ada saat 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 menginginkan informasi lebih lanjut tentang setiap topik dalam kursus ini, atau jika mengalami kesulitan, https://kotlinlang.org adalah langkah awal yang terbaik.

Tutorial Kotlin

Situs https://try.kotlinlang.org menyertakan berbagai tutorial yang disebut Kotlin Koans, penafsir berbasis web, dan kumpulan lengkap dokumentasi referensi dengan contoh.

Kursus Udacity

Untuk melihat kursus Udacity tentang topik ini, lihat Bootcamp Kotlin untuk Pemrogram

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. Terserah instruktur untuk melakukan hal berikut:

  • Tugaskan pekerjaan rumah jika diperlukan.
  • Berkomunikasi dengan siswa cara mengirimkan tugas pekerjaan rumah.
  • Beri nilai tugas pekerjaan rumah.

Instruktur dapat menggunakan saran ini sesedikit atau sebanyak yang mereka inginkan, dan harus bebas memberikan pekerjaan rumah lain yang dirasa sesuai.

Jika Anda mengerjakan codelab ini sendiri, silakan gunakan tugas pekerjaan rumah ini untuk menguji pengetahuan Anda.

Jawab pertanyaan ini

Pertanyaan 1

Manakah dari berikut ini yang merupakan konvensi untuk penamaan jenis generik?

<Gen>

<Generic>

<T>

<X>

Pertanyaan 2

Batasan jenis yang diizinkan untuk jenis umum disebut:

▢ batasan umum

▢ batasan generik

▢ disambiguasi

▢ batas jenis generik

Pertanyaan 3

Jika diperbarui berarti:

▢ Dampak eksekusi sebenarnya pada objek telah dihitung.

▢ Indeks entri yang dibatasi telah ditetapkan pada class.

▢ Parameter jenis generik telah diubah menjadi jenis yang 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: Selamat datang di kursus."