ProgramlamaOrta Seviye Kotlin Geliştirici

Kotlin'da scope fonksiyonları (let, also, run, apply, with) nedir? Bu fonksiyonlar arasındaki farklar nelerdir, farklı görevler için nasıl seçilirler, kullanımında hangi ince noktalar ortaya çıkabilir? Örnekler verin.

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Kotlin'deki scope fonksiyonları ("alan fonksiyonları") standart fonksiyonlardır (let, also, run, apply, with), bir nesne için kod bloğunun yürütme bağlamını yönetmeye olanak tanır. Bu fonksiyonlar şunlarla farklılık gösterir:

  • dönen değer tipi,
  • nesnenin blok içinde nasıl erişilebilir olduğu: it veya this ile.

Kısa karşılaştırma:

Fonksiyonthis/itDöndürürNe için?
letitsonuçişlem zinciri, null ile çalışma, haritalama
alsoitnesneyan etkiler, günlüğe kaydetme, hata ayıklama
runthissonuçhesaplamalar, geri dönüş ile başlangıç
applythisnesnenesne yapılandırması, yapıcılar
withthissonuçdış API ile çalışma, nesne "dışarıdan"

Örnekler:

  • let: nesne nullable olduğunda kullanışlıdır:
val str: String? = "Metin" str?.let { println(it.length) }
  • apply: nesne ayarları:
val paint = Paint().apply { color = Color.RED strokeWidth = 2f }
  • run: bir nesne üzerinde çalıştırma, sonucu geri döndürme:
val length = "abcde".run { length }
  • with: dış bir nesne ile çalışma:
val sb = StringBuilder() with(sb) { append("Merhaba, ") append("dünya!") toString() }
  • also: yan etkiler için (örneğin, günlüğe kaydetme):
val list = mutableListOf(1, 2, 3) list.also { println("Önce: $it") }.add(4)

Dikkat edilmesi gereken noktalar:

  • let nesneyi it içinde kopyalar, nesnenin özelliklerini değiştirmek pek pratik değildir.
  • apply ve also her zaman nesneyi geri döndürür (this / it), yapıcılar için faydalıdır.
  • run/with sıkça karıştırılır: with sıradan bir fonksiyondur, extension değildir.

İkna edici bir soru.

let ile also arasındaki fark nedir?

Cevap:

  • Her ikisi de blok içinde it kullanır,
  • let lambda sonucunu döndürür, genellikle dönüşüm zincirlerinde kullanılır,
  • also orijinal nesneyi döndürür, yan etkiler (örneğin, log, hata ayıklama) için kullanılır, dönüşüm zincirine müdahale etmez.

Örnek:

val result = listOf(1).also { println(it) }.map { it * 2 } // sonuç — List<Int>

Bilgisizlik nedeniyle ortaya çıkan gerçek hatalara örnekler:


Hikaye

Bir acemi, nesneyi "zincir içinde" ayarlamak için let kullandı, bunun sonucunda yapılandırma bloğunun sonunda nesneyi değil, lambda sonucunu (örneğin, hiçbiri) elde etti ve DSL oluşturma zinciri bozuldu.


Hikaye

Null nesnelerle çalışma kodu yazarken, geri dönen değerdeki farkı fark etmeden run yerine let kullandık. Sonuç olarak, sonuç ifadesi beklenenden farklı çıktı, beklenmeyen yerlerde null oluştu — uygulama mantığı bozuldu.


Hikaye

Büyük bir yapıcıda, iç nesneler için extension desenine güvenerek yanlışlıkla with kullandık. with bir extension fonksiyonu olmaması nedeniyle, birkaç with bloğundan oluşan zincir düzgün çalışmadı, iç çağrılar karıştı ve geçerli nesnenin sınırlarını aştı. Nesne oluşturma hiyerarşisini tamamen yeniden yazmak zorunda kaldık.