ProgramlamaiOS geliştirici, Orta/Senior

Swift'te tür silinmesi (type erasure) nedir, neden gereklidir ve pratikte doğru bir şekilde nasıl uygulanır?

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

Cevap.

Soru Tarihi: Tür silinmesi (type erasure) - Swift'te, ilişkili türler veya Self gereksinimleri olan protokollerin kısıtlamalarına bir yanıt olarak ortaya çıkan bir modeldir. İlişkili türler içeren bir protokol, tür silinmesi olmadan doğrudan tür olarak kullanılamaz, çünkü derleyici belirli bir uygulamanın ne olduğunu bilemez. Bu, veri kapları, koleksiyonlar, akışlar gibi yaratırken sıkça karşılaşılan bir durumdur, burada soyutlama önemlidir.

Sorun: Eğer ilişkilendirilmiş tür ile bir protokol varsa, örneğin:

protocol Animal { associatedtype Food func eat(_ food: Food) }

Animal türünde bir değişken tanımlamak mümkün değildir. Farklı somut türlere soyutlama aracılığıyla erişim sağlayan "silinmiş bir kapsayıcı" türe ihtiyacımız vardır:

let zoo: [any Animal] // Derleme hatası

Çözüm: Tür silinmesi, sarmalayıcılar (örneğin, Box modeli veya struct AnyXxx) kullanılarak gerçekleştirilir ve gerçek türün ayrıntılarını gizleyerek tek bir arayüz sağlar:

struct AnyAnimal<F>: Animal { private let _eat: (F) -> Void init<A: Animal>(_ base: A) where A.Food == F { _eat = base.eat } func eat(_ food: F) { _eat(food) } }

Artık aynı Food ile farklı Animal uygulamalarını saklayabiliriz:

let animals: [AnyAnimal<Grass>] = [AnyAnimal(Cow()), AnyAnimal(Sheep())]

Temel Özellikler:

  • İlişkili türler olan protokollerle sıradan türler gibi çalışmayı sağlar.
  • Evrensel konteynerler ve protokol varlıkları fabrikalarının sorununu çözer.
  • Uygulama ayrıntılarını gizlemek için mimari bir modeldir.

Çeldirici Sorular.

İlişkili türü olmayan bir protokolü tür özelliği veya dizisi olarak kullanmak mümkün mü?

Hayır, mümkün değil. Derleyici, tüm ilişkili türlerin kesinleştirilmesini gerektirir. Örneğin, aşağıdaki kayıt bir hataya neden olacaktır:

let array: [Animal] // Hata: 'Animal' yalnızca bir genel kısıtlama olarak kullanılabilir

Tür silinmesi, mirası (inheritance) ikame edebilir mi?

Hayır, tür silinmesi mirasın tam bir ikamesi değildir. İlişkili türler için soyutlama sorununu çözerken, miras sınıflar arasında ortak mantık ve kod yeniden kullanımı uygulamaları için kullanılır.

Tür silinmesi (type erasure) kapsayıcısının içindeki tüm protokol yöntem ve özelliklerini gerçekleştirmek gerekli mi?

Evet, zorunludur. Tür silinmesi, kapsayıcı protokolün dış arayüzünü tamamen tekrar etmesi durumunda çalışır, aksi takdirde bazı işlevler kullanılamaz.

Tipik Hatalar ve Anti-Desenler

  • Tüm yöntemleri/özellikleri uygulamayı unutur, bu da işlevselliğin sessiz kaybına yol açar.
  • Gereksiz tür silinmesi kullanır, bunun yerine kullanımını kaçırabilirler (örneğin, ilişkili tür yoksa).
  • Okunabilirliği azaltan aşırı veya karmaşık sarmalayıcılar oluştururlar.

Gerçek Hayattan Bir Örnek

Olumsuz Durum

Bir projede tüm veri kaynakları ile çalışmalar tür silinmesi üzerinden yürütülmektedir, ihtiyaç olmaksızın. Kodun bakımı zorlaşır, yeni geliştiriciler karışıklık yaşar.

Artılar:

  • API'nin evrenselliği

Eksiler:

  • Okunabilirliğin düşmesi, mimarinin karmaşıklaşması, gizli hatalar

Olumlu Durum

Tür silinmesi, farklı yükleme stratejilerini (ağ, yerel) kapsayan veri kaynağının soyutlaması için yalnızca uygulanmaktadır ve her biri kendi türlerine sahiptir. Diğer tüm kod açıktır.

Artılar:

  • Mimarinin esnekliği, yeni stratejilerin entegrasyonunun kolaylığı.

Eksiler:

  • Ara katmanlar (sarmalayıcılar) ekler, bu da hata ayıklamayı biraz zorlaştırır.