Selain mencocokkan nilai spesifik, when juga dapat mencocokkan tipe data menggunakan operator is. Cabang is String -> ... akan terpilih bila subjek bertipe String, dan kompilator secara otomatis mempersempit tipe statis ke String di dalam cabang tersebut. Proses ini disebut smart cast — fitur yang menghilangkan kebutuhan menulis cast eksplisit. Pada chapter ini kita akan memanfaatkan when dengan is untuk memproses daftar nilai heterogen, menggabungkan is dengan kondisi tambahan, serta menangani tipe nullable.

Pencocokan dengan is dan Smart Cast #

Saat cabang is String terpilih, kompilator memperlakukan subjek sebagai String non-nullable di dalam cabang tersebut. Akibatnya, kita dapat langsung memanggil .length atau .uppercase() tanpa perlu as String.

kotlin
fun main() {
    val input: Any = "Belajar Kotlin"

    // when dengan is: smart cast mengubah tipe di dalam branch
    val hasil = when (input) {
        is String -> "Panjang string: ${input.length}, huruf besar: ${input.uppercase()}"
        is Int -> "Integer, dua kalinya: ${input * 2}"
        is Double -> "Double, dibulatkan: ${input.toInt()}"
        is Boolean -> "Boolean, negasi: ${!input}"
        is List<*> -> "List berisi ${input.size} elemen"
        else -> "Tipe tidak dikenal"
    }
    println(hasil)

    // Proses daftar nilai Any dengan when + is
    val data: List<Any> = listOf("Budi", 25, 3.14, true, listOf(1, 2, 3), 100L)
    for (item in data) {
        val deskripsi = when (item) {
            is String -> "String '${item}' panjang ${item.length}"
            is Int -> "Int $item, kuadrat ${item * item}"
            is Double -> "Double $item"
            is Boolean -> "Boolean $item"
            is List<*> -> "List ${item.size} elemen"
            is Number -> "Number lain: $item"
            else -> "Tipe lain"
        }
        println(deskripsi)
    }

    // when pada nullable dengan is + smart cast
    val masukan: Any? = "Dewi"
    when (masukan) {
        is String -> println("String: '${masukan.uppercase()}' panjang ${masukan.length}")
        null -> println("Masukan null")
        else -> println("Tipe lain")
    }

    // Kombinasi is dengan kondisi tambahan menggunakan guard-like pola
    val angka: Any = 42
    when {
        angka is Int && angka > 0 -> println("Bilangan asli: $angka")
        angka is Int && angka < 0 -> println("Bilangan negatif: $angka")
        angka is Int -> println("Nol")
        else -> println("Bukan Int")
    }
}

Output yang Dihasilkan:

text
Panjang string: 14, huruf besar: BELAJAR KOTLIN
String 'Budi' panjang 4
Int 25, kuadrat 625
Double 3.14
Boolean true
List 3 elemen
Number lain: 100
String: 'DEWI' panjang 4
Bilangan asli: 42

Mari kita bedah bagian-bagian penting:

  1. is String -> "Panjang string: ${input.length} ...": karena input dideklarasikan Any, kompilator tidak mengetahui bahwa input punya property .length. Namun setelah cabang is String cocok, smart cast mengubah tipe statis input menjadi String, sehingga .length dan .uppercase() langsung dapat dipanggil.
  2. is Number -> "Number lain: $item": Number adalah superclass dari Int, Double, Long, dan tipe angka lainnya. Karena cabang is Int, is Double, dan is Boolean sudah dipasang sebelumnya, cabang is Number hanya menangkap sisa tipe angka seperti Long (yang muncul sebagai 100L pada data).
  3. when (masukan) { is String -> ...; null -> ...; else -> ... }: is String juga bekerja pada tipe nullable. Saat cabang is String cocok, masukan menjadi String non-nullable. Cabang null -> ... eksplisit menangani nilai null.
  4. when { angka is Int && angka > 0 -> ... }: bentuk tanpa argumen menggabungkan is dengan kondisi tambahan. Smart cast tetap aktif pada && kedua sehingga angka > 0 membandingkan angka sebagai Int.

Urutan Cabang Penting #

Karena evaluasi berhenti pada cabang pertama yang cocok, urutan cabang menentukan perilaku. Misalnya, bila is Number diletakkan sebelum is Int, maka semua Int akan ditangkap oleh is Number terlebih dahulu dan tidak pernah mencapai cabang yang lebih spesifik.

Smart Cast pada Nullable #

Operator is pada tipe nullable menggabungkan dua informasi sekaligus: tipe runtime dan keberadaan nilai. Setelah is String cocok pada Any?, kompilator memperlakukan subjek sebagai String non-nullable. Hal ini menghilangkan kebutuhan ?. di dalam cabang.

Perbandingan dengan Cast Manual #

PendekatanSintaksRisiko
is + smart castif (x is String) x.lengthAman, tipe dijamin
Cast manual asif (x is String) (x as String).lengthBekerja tapi redundan
Cast tanpa cek(x as String).lengthBerbahaya, lempar ClassCastException bila salah

Referensi Lanjutan #

  • Control flow — bagian when dengan is pada panduan control flow resmi
  • Smart casts — smart cast yang dipicu cabang is pada when

Dengan when + is, kita dapat memproses daftar heterogen tanpa perlu rangkaian if (x is T1) ... else if (x is T2) ... yang panjang. Pada chapter berikutnya kita beralih ke konstruksi loop, dimulai dengan for yang iteratif terhadap koleksi dan range.