Generic (ümumi proqramlaşdırma) — bu, Swift mexanizmidir, tipləri və funksiyaları parametrləşdirilmiş tip
Əsas məqamlar
Generic (ümumi tip) — bu, tipə görə parametrləşdirmə ilə çevik, təkrar istifadə oluna bilən kod yazmağa imkan verən Swift sintaktik konstruksiyasıdır. Konkret tip əvəzinə bucaqlı mötərizələrdə placeholder yazılır — adətən
Generic olmadan hər tip üçün ayrı funksiyalar yazmaq lazım gələrdi: swapInts, swapStrings, swapDates. Generic swap funksiyası hər üç variantı bir bəyannamə ilə əvəz edir. Bu, təkrarlanmanı azaldır, oxunaqlılığı artırır və kodu kopyalayarkən səhv ehtimalını azaldı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 kompilyatoru generic-in hər konkret istifadəsi üçün ixtisaslaşdırılmış kod yaradır. Bu o deməkdir ki, swapValues
Generic funksiyalar — bir və ya daha çox tip-parametr qəbul edən funksiyalardır. Tip-parametrlər funksiya adından sonra bucaqlı mötərizələrdə göstərilir:
Funksiyanın bir neçə generic parametri ola bilər. Məsələn, 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 və where V: Equatable məhdudiyyətləri findKey-in yalnız açarları heşlənə bilən və dəyərləri müqayisə oluna bilən lüğətlə çağrılmasını təmin edir. Bu cür məhdudiyyətlər bürokratiya deyil, zərurətdir: Hashable olmadan açar üzrə axtarışı indeksləşdirmək mümkün deyil, Equatable olmadan value-ni dictValue ilə müqayisə etmək mümkün deyil.
where — bu, generic parametrlərə əlavə məhdudiyyətlər qoyan Swift açar sözüdür. Bucaqlı mötərizələrdə protokolun sadə göstərilməsindən (
Where bəndi funksiya və ya tipin imzasından sonra, açılan qıvrım mötərizədən əvvəl yazılır. Where-də T: Comparable & Hashable (eyni anda iki protokol) və ya T.U == Int (associated type-ın konkretləşdirilməsi) göstərilə bilər.
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 ilə genişləndirmə yalnız şərti ödəyən tiplər üçün metodlar əlavə edir. Container
Associated Types (əlaqəli tiplər) — bu, bəyannamə mərhələsində konkret tipi göstərmədən protokolu ümumi etmək üsuludur.
Where vasitəsilə müxtəlif protokolların associated types arasında əlaqələr qurula bilər. Məsələn, bir protokolun Item-inin digərinin Iterator.Element-i ilə uyğun olması tələb edilə bilər. Bu, kompilyasiya səviyyəsində tiplərin uyğunluğunu təmin edir.
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 istifadə edərək Element-i Int olaraq konkretləşdirir. Kompilyator protokolun bütün tələblərinin bu tiplə yerinə yetirildiyini yoxlayır. Associated types olmadan generic protokol ilə StackProtocol
Generic genişləndirmələr əlavə məhdudiyyətlərlə generic tipə metodlar əlavə etməyə imkan verir. Bu, tipin funksionallığı yalnız müəyyən şərtlər altında aldığı “şərti uyğunluq” (conditional conformance) nümunəsidir. Subskriptlər də generic ola bilər.
Subskript ümumi ola bilər: bucaqlı mötərizələrdə generic parametrlər qəbul edir. Bu, indeksin müxtəlif tiplərdən ola biləcəyi ixtiyari indeksli kolleksiyalara təhlükəsiz giriş üçün faydalı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] }
}
}
Belə konstruksiya güclü kompozisiya verir: sum metodu yalnız ədədi massivlərdə görünür, ixtiyari indekslərlə subskript isə istənilən tam indeks ardıcıllığı ilə işləyir. Kompilyator where şərtləri əsasında bu üzvlərin görünməsini özü idarə edir.
Səhvlər generic istifadə edərkən çox vaxt yanlış məhdudiyyətlər və ya konkret tipin lazım olduğu yerdə generic istifadə etmək cəhdi ilə bağlıdır. Tərtibatçıların qarşılaşdığı üç ümumi ssenariyə baxaq.
Konkret tipin kifayət etdiyi yerdə generic parametrlər əlavə etmək — anti-nümunədir. Əgər funksiya həmişə String ilə işləyirsə, onu
Metodun mövcud olduğunu göstərmədən generic parametr üzərində metodu çağırmaq — səhvdir.
// ❌ 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 }
Səhv aydındır: generic
Tez-tez verilən suallar
Generic — bu, Int, String və digər tiplər üçün eyni məntiqi təkrarlamadan istənilən tiplə işləyən kod yazmaq üsuludur. Konkret tip əvəzinə istifadə zamanı real tiplə əvəz olunan placeholder
Generic kompilyasiya mərhələsində konkret tip haqqında məlumatı saxlayır ki, bu da kompilyatora tipləri yoxlamağa və optimallaşdırılmış kod yaratmağa imkan verir. Any — tip silməsidir: istənilən dəyər ötürülə bilər, lakin tip itir və çevirmə (as?) tələb olunur.
Bucaqlı mötərizələrdə T: SomeProtocol sintaksisindən və ya ayrıca where T: SomeProtocol bəndindən istifadə edin. Məhdudiyyətlər generic parametrin müəyyən metodları və xassələri dəstəkləməsini təmin edir.
Associated Type (associatedtype) — protokol daxilində tip üçün placeholderdir. Protokol konkret tipi göstərmir, associatedtype elan edir, o isə tətbiqdə konkretləşdirilir: Array-də Element, Dictionary-də Key və Value.
Swift generic kodu hər konkret tip üçün ixtisaslaşdırılmış versiyalara kompilyasiya edir. Praktikada Int üçün generic funksiya Int üçün əl ilə yazılmış funksiyadan yavaş deyil. Abstraksiyaya görə əlavə yük yoxdur.
Nəticə
Açar təslim mobil tətbiq hazırlayacağıq
IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.
Həm də oxuyun