Smart cast adalah fitur Kotlin yang membuat kompilator menyesuaikan tipe statis sebuah variabel berdasarkan pengecekan yang sudah dilakukan sebelumnya. Setelah if (x is String), kompilator memperlakukan x sebagai String di dalam blok tersebut tanpa perlu cast eksplisit. Demikian pula, setelah if (x != null), variabel nullable menjadi non-nullable di dalam blok. Fitur ini mengurangi boilerplate dan membuat kode lebih ringkas sekaligus aman. Pada chapter ini kita akan membedah smart cast pada if, when, &&, dan while, serta batasan-batasan praktisnya.
Smart Cast pada Operator is #
Operator is menguji apakah sebuah nilai merupakan tipe tertentu. Setelah pengujian positif, kompilator mempersempit tipe statis variabel pada cabang yang sesuai.
fun main() {
val nilai: Any = "Belajar Kotlin"
if (nilai is String) {
println("Panjang string: ${nilai.length}")
println("Huruf besar: ${nilai.uppercase()}")
println("Huruf kecil: ${nilai.lowercase()}")
}
val angka: Any = 42
if (angka is Int) {
val kuadrat: Int = angka * angka
println("Kuadrat: $kuadrat")
println("Apakah positif? ${angka > 0}")
}
when (nilai) {
is String -> println("String dengan panjang ${nilai.length}")
is Int -> println("Integer: $nilai")
is Boolean -> println("Boolean: $nilai")
else -> println("Tipe lain")
}
val x: Any? = "Dewi"
if (x != null && x is String) {
println("String non-null: ${x.uppercase()}")
}
val data: Any = 3.14
if (data is Double && data > 3.0) {
println("Double besar: $data")
}
val daftar: List<Any> = listOf("Budi", 25, true, "Siti")
for (item in daftar) {
when (item) {
is String -> println("String: '$item', panjang ${item.length}")
is Int -> println("Int: $item, dua kalinya ${item * 2}")
is Boolean -> println("Boolean: $item, negasi ${!item}")
}
}
val masukan: Any? = null
if (masukan is String) {
println("Tidak akan tercetak: ${masukan.length}")
} else {
println("Masukan bukan String (atau null)")
}
var kondisi: Any? = "Halo"
while (kondisi is String) {
println("Kondisi masih String: $kondisi")
kondisi = 0
}
println("Akhir loop")
}Output yang Dihasilkan:
Panjang string: 14
Huruf besar: BELAJAR KOTLIN
Huruf kecil: belajar kotlin
Kuadrat: 1764
Apakah positif? true
String dengan panjang 14
String non-null: DEWI
Double besar: 3.14
String: 'Budi', panjang 4
Int: 25, dua kalinya 50
Boolean: true, negasi false
String: 'Siti', panjang 4
Masukan bukan String (atau null)
Kondisi masih String: Halo
Akhir loopMari kita uraikan baris-baris penting pada contoh di atas:
- Baris 4 (
if (nilai is String)): setelahis Stringterbukti benar, kompilator memperlakukannilaisebagaiStringdi dalam blok. Karena itu.length,.uppercase(), dan.lowercase()dapat dipanggil tanpa cast eksplisit. - Baris 11 (
if (angka is Int)): smart cast juga bekerja untuk tipe numerik.angka * angkasekarang diizinkan karena kompilator tahuangkaadalahInt. - Baris 16-21 (
when (nilai) { is String -> ... }): setiap cabangwhenyang berbasisismempersempit tipe variabel pada cabang tersebut.nilai.lengthdapat dipanggil tanpa cast. - Baris 24 (
if (x != null && x is String)): smart cast bekerja pada kondisi gabungan&&. Karena&&mengevaluasi kiri-ke-kanan dan singkat-sirkuit (short-circuit), cabangx is Stringhanya dievaluasi bilax != null. Karena itu di dalam blok,xdiperlakukan sebagaiStringnon-nullable. - Baris 29 (
if (data is Double && data > 3.0)): kombinasi smart cast dengan operasi numerik. Setelahis Doublebenar, perbandingandata > 3.0menggunakan tipeDouble. - Baris 33-39 (iterasi
for (item in daftar)): smart cast bekerja pada variabel loop. Setiap cabangwhenmempersempititemke tipe yang sesuai sehingga method spesifik seperti.lengthatau!itemdapat dipanggil. - Baris 42-46 (
if (masukan is String)): variabel bertipeAny?— bilamasukanadalahnull, kondisiis Stringmengembalikanfalse(bukan melempar exception), sehingga cabangelseyang dijalankan. - Baris 49-52 (
while (kondisi is String)): smart cast juga berlaku pada kondisiwhile. Di dalam loop,kondisidiperlakukan sebagaiString. Loop berhenti setelahkondisiditetapkan ke0(bukanString).
Smart Cast Nullability #
Selain narrowing tipe, smart cast juga bekerja pada nullability. Setelah if (x != null), variabel x bertipe String? akan diperlakukan sebagai String non-nullable di dalam blok. Pengecekan != null ini menjadi cara paling alami untuk membuka akses langsung pada variabel nullable.
val nama: String? = ambilNama()
if (nama != null) {
println(nama.length)
}Pada blok if, nama.length dipanggil tanpa ?. karena kompilator sudah mempersempit tipe ke String.
Batasan Smart Cast #
Smart cast tidak diterapkan dalam beberapa situasi berikut:
- Properti
varyang dapat diakses publik dan dapat diubah dari luar. - Properti
openyang dapat di-override di subclass. - Variabel yang nilainya berasal dari delegate property kompleks.
- Variabel lokal
varyang dipakai dalam lambda yang ditangkap (captured), karena dapat berubah antara pengecekan dan pemakaian.
Pada kasus-kasus tersebut, kompilator meminta kita melakukan cast eksplisit menggunakan as atau as? (lihat chapter Safe Cast).
Referensi Lanjutan #
- Smart casts
— panduan resmi smart cast otomatis setelah pengecekan
is - Type casts
— konteks
isdanaspada panduan typecasts
Setelah memahami smart cast, langkah berikutnya adalah mempelajari pola pengecekan null dengan != null dan == null secara lebih dalam — topik yang akan kita bahas pada chapter Null Checking.