Soru tarihi:
Elvis operatörü (?:), Kotlin'de nullable değerlerin işlenmesi için kısa ve güvenli bir yöntem olarak ortaya çıktı. Adını, operatörün yan tarafından bakıldığında Elvis Presley'in saçına benzerliğinden alır. Amacı, if (a != null) a else b gibi şablon kodlardan kurtulmak ve günlük geliştirmeyi daha rahat hale getirmektir.
Problem:
Null olabilecek bir değere doğrudan erişmek, çalışma zamanı hatasına (NullPointerException) neden olur. Bu nedenle, bir değişken null olduğunda varsayılan değerleri zarif bir şekilde yerleştirebilen bir araca ihtiyaç vardır.
Çözüm:
Elvis operatörü nullable tipler üzerinde uygulanabilir. Eğer operatörün solundaki ifade null değilse, o ifade döner, aksi takdirde sağdaki ifade döner. Bu, kodu daha kompakt ve güvenli hale getirir.
Kod örneği:
fun getLength(str: String?): Int { return str?.length ?: 0 } val result = getLength(null) // result == 0 val result2 = getLength("Hello") // result2 == 5
Ana özellikler:
Elvis operatörünün sağında yan etkisi olan bir ifade olursa ne olur? Her zaman mı çalışır?
Hayır! Sağdaki ifade, soldaki ifade null olduğunda yalnızca hesaplanır. Bu, fonksiyon yan etkilere veya "maliyetli" hesaplamalara sahipse önemli olabilir.
Kod örneği:
var called = false val x: String? = "test" val y = x ?: run { called = true; "default" } // called false olacak çünkü run hiç çalışmayacak
Elvis operatörünü istisna fırlatmak için kullanabilir miyiz?
Evet, Kotlin'de şöyle yazabilirsiniz:
fun getLengthStrict(str: String?): Int = str?.length ?: throw IllegalArgumentException("str is null")
Eğer str null ise, bir istisna fırlatılacak. Bu, veri doğrulama için kullanışlı bir mekanizmadır.
Birden fazla Elvis operatörünü artarda "birleştirmek" mümkün mü?
Evet, bu bir geri dönüş için olağan bir yaklaşımdır:
val name = fromDatabase ?: fromCache ?: "Unknown"
Bu ifade, ilk NULL olmayan değeri veya "Unknown" dizesini döndürecektir.
Elvis üzerinden çok katmanlı null kontrolü:
val title = a?.b?.c?.d?.e ?: defaultTitle
Artıları:
Eksileri:
Adım adım açık bir parçalama, net değişken isimleri:
val deepValue = a?.b val deeperValue = deepValue?.c?.d ?: default
Artıları:
Eksileri: