Kotlin dilinde standart yüksek düzey fonksiyonlar olan apply, also, let ve run, nesnelerin zincirleme yapılandırılmasını ve yerel değişikliklerini minimum şablon kodu ile gerçekleştirmek için geliştirilmiştir. Bu fonksiyonlar, değişken ve sabit nesnelerle çalışmayı kolaylaştırır, dönüşüm zincirlerini kısaca ifade etme imkanı sunar ve değişkenlerin geçici kapsamı ile ilgili problemleri azaltır.
Bu fonksiyonlar, yapıcı deseninden ve akıcı arayüz yaklaşımlarından alınmıştır. Kodun daha temiz olmasını sağlama ve yardımcı değişkenlerin gereksiz ilanından kurtulma arzusu ile ortaya çıkmıştır.
Standart yaklaşım, nesneye çok kez erişim gerektirir veya geçici değişkenlerin çıkarılmasını talep eder. Bu, okunabilirliği düşürür ve hata riskini artırır:
val user = User() user.name = "Alex" user.age = 26 user.isActive = true
apply, also, let ve run fonksiyonlarının kullanımı ifadeliliği artırır:
val user = User().apply { name = "Alex" age = 26 isActive = true }
Kısa tanımlar:
data class User(var name: String = "", var age: Int = 0, var isActive: Boolean = false) val configuredUser = User().apply { name = "Alice" age = 30 isActive = true } debugUser(configuredUser.also { println("User is configured: $it") }) val emailLength = configuredUser.email?.let { it.length } ?: 0 val description = configuredUser.run { "$name ($age)" }
Anahtar özellikler:
Let fonksiyonu nesneyi değiştirebilir mi?
Let fonksiyonu, nesneyi değiştirmek için tasarlanmamıştır. Daha çok bir değere dönüşüm uygulamak için kullanılır ve sonucu döndürür. Unutulmamalıdır ki, let içinde this yerine it erişimi vardır.
val upperName = user.name.let { it.uppercase() } // let user'ı değiştirmez
Apply ile run arasındaki fark nedir?
Her ikisi de lambda içinde this bağlamıyla çalışır, geri dönüş değerlerinde farklılık vardır:
// apply val building = StringBuilder().apply { append("start-") append("end") } // building — bu StringBuilder'dır. // run val result = StringBuilder().run { append("start-") append("end") toString() } // result — bu bir String'dir.
Apply ve let birbirine gömülebilir mi? Eğer evet, ne zaman makuldür?
Evet, iç içe kullanım, nesnelerin birikmesi veya adım adım yapılandırılması için nazikçe önerilir, özellikle nullable ile çalışırken:
val userInfo = user?.apply { isActive = true }?.let { "${it.name} is active: ${it.isActive}" }
Kodun her yerinde nesneyi değiştirmek için let kullanılır, apply ve let karıştırılır — sonunda nesne beklenildiği gibi değişmez, değeri de zincirlerde kaybolur.
Artılar:
Eksiler:
Yapılandırma ve günlüğe kaydetme için apply ve also kullanılır, let yalnızca nullable ile çalışma ve sonuç elde etmek için, run — hesaplama gerektiren dönüşüm zincirleri için kullanılır.
Artılar:
Eksiler: