ProgramlamaOrta Seviye Android Geliştirici

Kotlin'de koleksiyonların ve nesnelerin değişmezliği (immutability) nasıl gerçekleştirilmiştir ve uygulama Java'dan ne şekilde farklıdır?

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

Cevap

Soru geçmişi:

Java'da koleksiyonların değişmezliği, Collections.unmodifiableList() gibi sarmalayıcılar aracılığıyla ve immutable sınıfların manuel olarak tasarlanması (final alanlar, setter'ların olmaması) ile sağlanır. Android ve sunucu geliştirme pratiğinde bu yöntemler sıkça zahmetli ve kullanışsız hale gelmiştir ve çoklu iş parçacıkları güvenliği ile veri öngörülebilirliği kaybolmuştur.

Sorun:

Java koleksiyonları varsayılan olarak güvenli değildir; her zaman bir referans alıp nesneyi değiştirmek mümkündür. Bu, değişmezliği kontrol etmeyi zorlaştırır, özellikle çoklu iş parçacığı ortamlarında ve zor tespit edilen hatalara yol açar.

Çözüm:

Kotlin, başlangıçta okunabilir ve değiştirilebilir koleksiyonların ayrımı ile tasarlandı ve gerçekten değişmez nesneler oluşturma süreci val, data class ve List/Set/Map gibi yapılarla daha kolay hale geldi (mutable ön eki olmadan). Bunun üzerine — copy() yöntemleri aracılığıyla kopyalama yapılabilmektedir.

Kod örneği:

val nums: List<Int> = listOf(1, 2, 3) // değişmez liste // nums.add(4) // derleme hatası val user = User(name = "Alex", age = 30) val updated = user.copy(age = 31) // Değişmez harita örneği val state: Map<String, Int> = mapOf("a" to 1, "b" to 2)

Ana özellikler:

  • Read-only koleksiyonu değiştirmeye çalışmak derleme hatası verir
  • Kotlin'de val, referansın değişmezliğini garanti eder, ancak nesnenin değişmezliğini garanti etmez
  • Gerçekten değişmez nesneler için yalnızca read-only arayüzleri kullanın ve içsel durumun değişmesini yasaklayın

İkna edici sorular.

Val, iç nesnenin mutlak değişmezliğini garanti eder mi?

Hayır! Val, yalnızca değişkenin başka bir nesneye işaret etmemesini garanti eder, ancak iç nesnenin alanları değiştirilebilir (eğer iç özellikler var ise).

Read-only koleksiyondan değiştirilebilir bir nesne elde edilebilir mi?

Evet — eğer koleksiyon değiştirilebilir bir nesne içeriyorsa, read-only arayüzüne rağmen durumu değiştirebilirsiniz.

data class User(var name: String) val users: List<User> = listOf(User("Vasya")) users[0].name = "Petya" // geçerli

List<Int> türünü MutableList<Int> türüne as? ile çevirdiğinizde ne olur?

Derlenir, ancak eğer başlangıç türü read-only arayüzse çalışma zamanında ClassCastException'a yol açar.

Yaygın hatalar ve anti-patternler

  • Val'i iç nesnenin mutlak değişmezliği için kesin bir garanti olarak kabul etmek
  • "Immutable" koleksiyonlar içindeki değiştirilebilir nesnelere referans manipülasyonu yapmak
  • Read-only koleksiyonları değiştirilebilir hale getirmek

Gerçek bir örnek

Negatif durum

Bir Android uygulaması durumu val List<User> içinde saklıyor ve bunu değişmez olarak kabul ediyor. Geliştiricilerden biri user.name'i değiştiriyor. Başka bir parçada güncellenmiş liste, beklenmedik biçimde tutarsız verileri gösteriyor — hata, sürümde ortaya çıkıyor.

Artılar:

  • Koleksiyonlarla hızlı çalışma

Eksiler:

  • Mutasyonlar üzerinde kontrol kaybı
  • Gizli değişkenlik

Pozitif durum

Sadece val alanları ile değişmez data class kullanımı, iç nesnelere erişim filtrelemesi, durumu copy() ile güncelleme.

Artılar:

  • Yüksek öngörülebilirlik ve iş parçacığı güvenliği
  • Beklenmedik yan etkilerin olmaması

Eksiler:

  • Bazen daha fazla bellek tahsisi ve kopyalama gerektirir
  • Tüm harici kütüphaneler gerçekten değişmez nesneler sunmaz