ProgramlamaKotlin geliştirici

Kotlin'de shallow copy ve deep copy arasındaki farkı açıklayın. Nesnelerin derin kopyalanmasını nasıl gerçekleştirebiliriz ve karmaşık yapıların kopyalanmasındaki tipik hatalar nelerdir?

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

Cevap.

Kotlin'de, shallow copy (yüzeysel kopyalama) yeni bir nesne oluşturur, ancak iç içe nesneler (örneğin, koleksiyon elemanları veya referans alanları) kopyalanmaz, aynı nesneye işaret ederler ki bu da orijinal örnekle aynıdır. Deep copy (derin kopyalama), tüm iç nesnelerin (nesne grafiği) özyinelemeli olarak kopyalanması anlamına gelir, böylece orijinal ve kopya tamamen bağımsız olur.

Kotlin standart kütüphanesinde derin kopyalama için evrensel bir araç yoktur ve manuel olarak uygulanması gerekir, özellikle karmaşık yapılar veya döngü içeren graf yapıları için.

Yüzeysel kopyalamaya örnek:

data class Person(val name: String, val addresses: List<String>) val original = Person("Anna", listOf("Moskova", "Londra")) val shallow = original.copy() println(original.addresses === shallow.addresses) // true, aynı referans

Derin kopyalamaya örnek:

data class Person(val name: String, val addresses: List<String>) { fun deepCopy(): Person = Person(name, addresses.toList()) } val deep = original.deepCopy() printfn(original.addresses === deep.addresses) // false, yeni liste kopyası

Kandırmaca sorusu.

Eğer iç içe koleksiyonlara sahip bir data class için .copy() kullanılırsa, koleksiyonlar kopyalanacak mı? Neden?

Cevap ve örnek:

Hayır, copy() yüzeysel bir kopya oluşturur. İç içe koleksiyonlar ve nesneler aynı nesnelere işaret etmeye devam eder. Bu nesnelerdeki herhangi bir değişiklik hem orijinalde hem de kopyada görülecektir, bu da hatalara yol açabilir.

data class Box(val items: MutableList<String>) val box1 = Box(mutableListOf("A")) val box2 = box1.copy() box2.items.add("B") printfn(box1.items) // [A, B] — orijinal de değişti!

Konunun inceliklerini bilmemekten kaynaklanan gerçek hata örnekleri.


Hikaye

Bir projede nesnenin durumunu sıradan .copy() ile kaydediyorduk, 'anlık görüntü' elde ettiğimizi düşünüp eski duruma döndüğümüzde iç içe liste (mutableList) tüm kopyalarda değişmiş oluyordu çünkü yüzeysel kopyalama yapmıştık.


Hikaye

Belge sisteminde varlıkları Gson ile serileştirme/demirleme yoluyla kopyalayarak derin kopyalama bekliyorduk, ancak nullable alanlar ve tarihler yanlış serileştirildi — sonuç olarak hatalı değerler ve iş mantığı hataları ortaya çıktı.


Hikaye

Android geliştirme için Redux benzeri bir depoya durum geçişi yaparken, copy() kullanarak durum ağaçları için tam bağımsızlık bekleyerek yapıyorduk. Sonuçta, bir yaklaşım depodaki başka bir durumun değişmesine neden olabiliyordu çünkü aynı iç mutable koleksiyonlarına referans veriyordu.