0Pricing
Kotlin Academy · Pelajaran

Variansi di Lokasi Deklarasi

in dan out

Variansi di Lokasi Deklarasi adalah pelajaran Kotlin Academy gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Kotlin Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Kotlin Academy mencakup 4 pelajaran total.

Masalah Varians

Apakah List<String> merupakan jenis List<Any>? Terkadang ya, terkadang tidak. Varians menjelaskan hubungan antartipe generik ketika parameter tipenya saling berhubungan. Kotlin menggunakan out dan in untuk menyatakannya.

Generik Invarian secara Default

Secara default, generik bersifat invarian: Box<String> BUKAN Box<Any>, meskipun tipe teks merupakan subtipe dari tipe umum. Hal ini mencegah operasi yang tidak aman.

class Box<T>(val value: T)

fun main() {
    val strBox = Box("hi")
    // val anyBox: Box<Any> = strBox // would not compile
    println(strBox.value)
}

Kovarians dengan out

Menandai parameter tipe dengan out membuatnya kovarian: Producer<String> menjadi subtipe dari Producer<Any>. Tipe tersebut hanya dapat muncul pada posisi keluaran, yaitu tipe hasil.

class Producer<out T>(private val item: T) {
    fun produce(): T = item
}

fun main() {
    val strProducer: Producer<String> = Producer("hello")
    val anyProducer: Producer<Any> = strProducer
    println(anyProducer.produce())
}

Mengapa out Aman

Jika sebuah kelas hanya menghasilkan atau mengembalikan T dan tidak pernah menerimanya, memperlakukan Producer<String> sebagai Producer<Any> aman, karena setiap nilai bertipe teks yang dikembalikannya juga merupakan nilai bertipe umum.

out di Pustaka Standar

List<out E> yang hanya dapat dibaca di Kotlin bersifat kovarian. Itulah sebabnya List<String> dapat digunakan ketika List<Any> diharapkan.

fun printAll(items: List<Any>) {
    items.forEach { println(it) }
}

fun main() {
    val names: List<String> = listOf("Ann", "Bob")
    printAll(names)
}

Kontravarians dengan in

Menandai parameter tipe dengan in membuatnya kontravarian: Consumer<Any> menjadi subtipe dari Consumer<String>. Tipe tersebut hanya dapat muncul pada posisi masukan, yaitu parameter.

class Consumer<in T> {
    fun consume(item: T) {
        println("Consumed $item")
    }
}

fun main() {
    val anyConsumer: Consumer<Any> = Consumer()
    val strConsumer: Consumer<String> = anyConsumer
    strConsumer.consume("hi")
}

Mengapa in Aman

Komponen penerima yang menerima nilai bertipe umum tentu dapat menerima nilai bertipe teks. Jadi, Consumer<Any> dapat digunakan di mana pun Consumer<String> diperlukan.

Mnemonik PECS

Ingat: Producer menghasilkan, Consumer menerima supertipe, atau dalam istilah Kotlin: out untuk penghasil (keluaran) dan in untuk penerima (masukan). Tipe yang hanya menghasilkan T menggunakan out; tipe yang hanya menerima T menggunakan in.

Menggabungkan in dan out

Parameter tipe yang digunakan untuk masukan dan keluaran sekaligus, seperti pada daftar yang dapat diubah, harus tetap invarian. Tipe fungsi menunjukkan keduanya: parameternya adalah in, sedangkan hasil pengembaliannya adalah out.

fun main() {
    val f: (Number) -> Int = { it.toInt() }
    val g: (Int) -> Number = f
    println(g(3.0.let { Number::class; 5 }))
}

Varians di Deklarasi Berarti Satu Tempat

Varians di deklarasi ditetapkan satu kali pada kelas itu sendiri dengan in/out. Setiap penggunaan kelas tersebut kemudian mendapatkan varians secara otomatis, berbeda dengan Java yang mengharuskan Anda mengulang karakter pengganti di setiap penggunaan.

Memilih in atau out

Tanyakan: apakah kelas ini hanya menghasilkan T (gunakan out), hanya menerima T (gunakan in), atau melakukan keduanya (biarkan invarian)? Menyesuaikan pengubah dengan perannya membuat tipe generik Anda fleksibel dan aman.

Pemeriksaan Singkat

Apa yang ditunjukkan oleh pengubah out?

Ringkasan

Generik bersifat invarian secara default. Gunakan out untuk kovarians ketika suatu tipe hanya menghasilkan nilai, dan in untuk kontravarians ketika tipe tersebut hanya menerima nilai. Ingat, penghasil menggunakan out dan penerima menggunakan in. Selanjutnya, Anda akan menerapkan varians pada titik penggunaan dengan proyeksi tipe.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Variansi di Lokasi Deklarasi” gratis?

Ya — teks lengkap “Variansi di Lokasi Deklarasi” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Kotlin Academy, upgrade ke CoddyKit PRO. Kursus Kotlin Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Variansi di Lokasi Deklarasi”?

in dan out Kamu berlatih Kotlin Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Kotlin Academy?

Tidak diperlukan pengalaman sebelumnya. Kotlin Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Variansi di Lokasi Deklarasi” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Kotlin Academy ini?

Ya. Setiap pelajaran Kotlin Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Fungsi dan Kelas Generik
  2. Variansi di Lokasi Deklarasi
  3. Variansi di Lokasi Penggunaan
  4. Batasan Generik
← Kembali ke Kotlin Academy