Kendine özgü generic parametreler, Swift'te associatedtype anahtar kelimesi ile protokollerde, davranışın soyutlanmasında daha fazla kontrol sağlamak için ilk Swift sürümünden itibaren mevcut.
Eğer bir protokol, belirli bir türün tanımlanması gereken bir talep ortaya koyuyorsa (örneğin, bir konteynerdeki öğe türü), associatedtype olmadan bu protokolle çalışmak imkansız hale gelir: türler katı bir şekilde tanımlanmalıdır, genel kod yazma olanağı kaybolur.
associatedtype, bir protokole bağlı bir türü tanımlamak için deklaratif olarak bildirim yapılmasına olanak tanır, bu da protokolleri ve generic fonksiyonları, derleme aşamasında belirli türleri bilmeden yazmayı mümkün kılar.
Örnek bir associatedtype'e sahip protokol:
protocol MyContainer { associatedtype Item var count: Int { get } mutating func append(_ item: Item) subscript(i: Int) -> Item { get } } struct IntStack: MyContainer { var items = [Int]() mutating func append(_ item: Int) { items.append(item) } var count: Int { items.count } subscript(i: Int) -> Int { items[i] } // Swift, Item'in Int olduğunu kendisi çıkarır }
Ana özellikler:
let x: MyContainer // hata),Erağam varsa, associatedtype'e neden ihtiyacımız var?
Cevap: Generics ve associatedtype benzer ama farklı sorunları çözmektedir. Generic parametre, tür veya fonksiyonu kapsayarak, generic yapıların ve metodların oluşturulmasına olanak tanır. Associatedtype ise, uygulanan türlerin kendi türünü tanımlaması için bir gereklilik oluşturan protokol içindeki bir soyutlamadır. Universel algoritmalar veya konteynerler için generic kullanın, protokoller aracılığıyla davranış için associatedtype'i kullanın.
Associatedtype'e sahip bir protokolü değişken türü olarak kullanabilir miyim?
Hayır, Swift, bu tür protokolleri doğrudan tür olarak kullanmaya izin vermez, çünkü associatedtype hakkında bilgi kaybolur. Soyutlama için type erasure yapılabilir veya generic kısıtlamalar kullanılabilir:
func printElements<C: MyContainer>(container: C) { for i in 0..<container.count { print(container[i]) } }
Associatedtype'e sahip bir protokolü "tür" (type erasure) olarak nasıl yapabilirim?
Bunun için type erasure desenini kullanarak, closure veya box aracılığıyla iç uygulamayı saklayan bir sarmalayıcı oluşturur.
struct AnyContainer<T>: MyContainer { private let _append: (T) -> Void private let _count: () -> Int private let _subscript: (Int) -> T ... // closure'lar aracılığıyla başlatma }
Bir geliştirici, veri modelleri için birden fazla protokol oluşturmuş ve ardından let boxes: [MyContainer] adlı bir dizi oluşturmaya çalışmış, fakat derleyici hata vermiştir. Sonunda gereksiz sarmalayıcılar eklemek zorunda kalmış ve tür güvenliğini kaybetmiştir.
Artılar:
Eksiler:
Projede associatedtype'e sahip bir protokol, koleksiyonların uygulanması için kullanılmış ve onlarla çalışma soyutlaması için ayrı bir type erasure sarmalayıcı AnyCollection oluşturulmuştur. Bu, koleksiyonların belirli uygulamalarından soyutlanmayı sağlar ve iş mantığı katmanında tür güvenliğini kaybetmemeyi mümkün kılar.
Artılar:
Eksiler: