Generic (genel programlama) — Swift'te, parametrelendirilmiş bir tür
Ana Noktalar
Generic (genel tür) — Swift'te, tür parametrelendirmesiyle esnek, yeniden kullanılabilir kod yazmayı sağlayan bir sözdizimsel yapıdır. Somut bir tür yerine, açılı parantezler içinde bir yer tutucu yazılır — genellikle
Generics olmadan, her tür için ayrı işlevler yazmak gerekirdi: swapInts, swapStrings, swapDates. Tek bir genel swap işlevi, üç değişkeni de tek bir bildirimle değiştirir. Bu, çoğaltmayı azaltır, okunabilirliği artırır ve kod kopyalarken hata olasılığını düşürür.
func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
var x = 10
var y = 20
swapValues(&x, &y)
Swift derleyicisi, bir generic'in her somut kullanımı için özelleştirilmiş kod üretir. Bu, swapValues
Genel işlevler, bir veya daha fazla tür parametresini kabul eden işlevlerdir. Tür parametreleri, işlev adından sonra açılı parantezler içinde belirtilir:
Bir işlev çoklu genel parametreye sahip olabilir. Örneğin, findKey
func findKey<K: Hashable, V>(
for value: V,
in dictionary: [K: V]
) -> K? where V: Equatable {
for (key, dictValue) in dictionary {
if dictValue == value {
return key
}
}
return nil
}
K: Hashable ve where V: Equatable kısıtlamaları, findKey'in yalnızca anahtarları hashlenebilir ve değerleri karşılaştırılabilir olan bir sözlükle çağrılabilmesini sağlar. Bu tür kısıtlamalar bürokrasi değil, bir gerekliliktir: Hashable olmadan anahtar araması indekslenemez, Equatable olmadan value ile dictValue karşılaştırılamaz.
where — Swift'te genel parametrelere ek kısıtlamalar getiren bir anahtar kelimedir. Açılı parantezler içinde basitçe bir protokol belirtmenin (
where cümlesi, işlev veya tür imzasından sonra, açılı küme parantezinden önce yazılır. where içinde T: Comparable & Hashable (aynı anda iki protokole uygunluk) veya T.U == Int (bir associated type'ı somutlaştırma) belirtilebilir.
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int { get }
}
extension Container where Item: Comparable {
func isSorted() -> Bool {
// Implementation available only if Item: Comparable
return true
}
}
where ile uzantı, koşulu karşılayan türler için yöntemler ekler. Container
Associated Types (ilişkili türler) — bir protokolü bildirim aşamasında somut bir tür belirtmeden genel hale getirmenin bir yoludur.
where kullanarak farklı protokollerin associated type'ları arasında ilişkiler kurulabilir. Örneğin, bir protokolün Item'ının diğerinin Iterator.Element'iyle eşleşmesi istenebilir. Bu, derleyici düzeyinde tür uyumluluğunu garanti eder.
protocol StackProtocol {
associatedtype Element
mutating func push(_ item: Element)
mutating func pop() -> Element?
}
struct IntStack: StackProtocol {
typealias Element = Int
private var items: [Int] = []
mutating func push(_ item: Int) { items.append(item) }
mutating func pop() -> Int? { items.popLast() }
}
IntStack, typealias kullanarak Element'i Int olarak somutlaştırır. Derleyici, protokolün tüm gereksinimlerinin bu türle karşılandığını doğrular. Associated type'lar olmadan, genel bir protokolle StackProtocol
Genel uzantılar, ek kısıtlamalarla genel bir türe yöntem eklemeye olanak tanır. Bu, bir türün yalnızca belirli koşullarda işlevsellik kazandığı “koşullu uygunluk” modelidir. Alt simgeler de genel olabilir.
Bir alt simge genel olabilir: açılı parantezler içinde genel parametreleri kabul eder. Bu, dizinin farklı türlerde olabileceği durumlarda, rastgele dizinlerle koleksiyonlara güvenli erişim için kullanışlıdır.
extension Array where Element: Numeric {
func sum() -> Element {
return reduce(0, +)
}
}
extension Array {
subscript<Indices: Sequence>(indices: Indices) -> [Element]
where Indices.Element == Int {
return indices.map { self[$0] }
}
}
Bu yapı güçlü bir bileşim sağlar: sum yöntemi yalnızca sayısal dizilerde görünür ve rastgele dizinlerle alt simge, tamsayı dizinlerinin herhangi bir dizisiyle çalışır. Derleyici, where koşullarına göre bu üyelerin görünürlüğünü yönetir.
Hatalar, genellikle yanlış kısıtlamalar veya somut bir türün gerekli olduğu yerde genel kullanma girişimiyle ilgilidir. Geliştiricilerin karşılaştığı üç yaygın senaryoyu inceleyelim.
Somut bir türün yeterli olduğu yere genel parametreler eklemek bir anti-kalıptır. Bir işlev her zaman String ile çalışıyorsa, onu
Yöntemin var olduğunu belirtmeden genel bir parametrede yöntem çağırmak bir hatadır. T: Collection belirtilmezse
// ❌ Error: value has no count method
func countElements<T>>(value: T) -> Int { value.count }
// ✅ Works: T: Collection guarantees count exists
func countElements<T: Collection>(value: T) -> Int { value.count }
Hata açıktır: genel
Sıkça Sorulan Sorular
Generic, Int, String ve diğer türler için aynı mantığı kopyalamadan her türle çalışan kod yazmanın bir yoludur. Somut bir tür yerine, kullanım noktasında gerçek türle değiştirilen bir yer tutucu
Generic, derleme zamanında somut tür hakkındaki bilgileri korur, derleyicinin türleri denetlemesine ve optimize edilmiş kod üretmesine olanak tanır. Any, tür silmedir: herhangi bir değer iletilebilir, ancak tür kaybolur ve dönüştürme (as?) gerekir.
Açılı parantezler içinde T: SomeProtocol sözdizimini veya ayrı bir where cümlesi where T: SomeProtocol kullanın. Kısıtlamalar, genel parametrenin belirli yöntemleri ve özellikleri desteklemesini sağlar.
Associated Type (associatedtype), bir protokol içindeki bir tür için yer tutucudur. Protokol somut bir tür belirtmez, bunun yerine bir associatedtype bildirir ve bu, uygulamada somutlaştırılır: Array'in Element'i, Dictionary'in Key ve Value'su vardır.
Swift, genel kodu her somut tür için özelleştirilmiş sürümlerde derler. Pratikte, Int için bir genel işlev, Int için elle yazılmış bir işlevden daha yavaş değildir. Soyutlama ek yükü yoktur.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun