Generic (általános programozás) — egy Swift mechanizmus, amely lehetővé teszi típusok és függvények írását paraméterezett típussal
Főbb pontok
Generic (általános típus) — egy szintaktikai szerkezet Swiftben, amely lehetővé teszi rugalmas, újrafelhasználható kód írását típus paraméterezéssel. Konkrét típus helyett egy helyőrző kerül a szögletes zárójelekbe — általában
Generic nélkül külön függvényeket kellene írni minden típushoz: swapInts, swapStrings, swapDates. A generic swap függvény mindhárom változatot egyetlen deklarációval helyettesíti. Ez csökkenti az ismétlést, növeli az olvashatóságot és csökkenti a hibák valószínűségét a kód másolásakor.
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)
A Swift fordító specializált kódot generál minden egyes konkrét generic használathoz. Ez azt jelenti, hogy a swapValues
Generic függvények — olyan függvények, amelyek egy vagy több típus-paramétert fogadnak el. A típus-paraméterek a függvény neve után szögletes zárójelekben kerülnek megadásra:
Egy függvénynek több generic paramétere lehet. Például a 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
}
A K: Hashable és where V: Equatable megszorítások garantálják, hogy a findKey csak olyan szótárral hívható meg, amelynek kulcsai hash-elhetők és értékei összehasonlíthatók. Az ilyen megszorítások nem bürokrácia, hanem szükségszerűség: Hashable nélkül nem lehet indexelni a kulcs szerinti keresést, Equatable nélkül nem lehet összehasonlítani a value-t a dictValue-val.
where — egy Swift kulcsszó, amely további megszorításokat ró a generic paraméterekre. Ellentétben a protokoll egyszerű megadásával szögletes zárójelekben (
A where záradék a függvény vagy típus aláírása után, a nyitó kapcsos zárójel előtt íródik. A where-ben megadható, hogy T: Comparable & Hashable (egyidejűleg két protokoll), vagy hogy T.U == Int (associated type konkretizálása).
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
}
}
A where-es kiterjesztés csak azokhoz a típusokhoz ad metódusokat, amelyek teljesítik a feltételt. A Container
Associated Types (kapcsolódó típusok) — egy mód arra, hogy a protokoll általánossá váljon anélkül, hogy a deklarációs fázisban megadnánk a konkrét típust. A
A where segítségével kapcsolatok hozhatók létre a különböző protokollok associated types között. Például előírható, hogy az egyik protokoll Item-je egyezzen meg a másik Iterator.Element-jével. Ez garantálja a típusok kompatibilitását fordítási szinten.
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() }
}
Az IntStack a typealias segítségével Element-et Int-ként konkretizálja. A fordító ellenőrzi, hogy a protokoll összes követelménye teljesül-e ezzel a típussal. Associated types nélkül StackProtocol
Generic kiterjesztések lehetővé teszik metódusok hozzáadását egy generic típushoz további megszorításokkal. Ez a „feltételes megfelelés” minta, amikor a típus csak bizonyos feltételek mellett kap funkcionalitást. A subscriptek is lehetnek generic-ek.
Egy subscript lehet általános: generic paramétereket fogad el szögletes zárójelekben. Ez hasznos a gyűjteményekhez való biztonságos hozzáféréshez tetszőleges indexszel, amikor az index különböző típusú lehet.
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] }
}
}
Az ilyen szerkezet erőteljes kompozíciót biztosít: a sum metódus csak numerikus tömböknél jelenik meg, a tetszőleges indexű subscript pedig bármilyen egész indexsorozattal működik. A fordító maga kezeli ezeknek a tagoknak a láthatóságát a where feltételek alapján.
Hibák a generic használatakor gyakran kapcsolódnak helytelen megszorításokhoz vagy a generic használatának kísérletéhez ott, ahol konkrét típusra van szükség. Vizsgáljunk meg három gyakori forgatókönyvet, amellyel a fejlesztők találkoznak.
Generic paraméterek hozzáadása ott, ahol a konkrét típus elegendő — egy anti-minta. Ha egy függvény mindig String-tel dolgozik, nem kell
Metódus hívása egy generic paraméteren anélkül, hogy megadnánk, hogy a metódus létezik — hiba.
// ❌ 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 }
A hiba érthető: a generic
Gyakran Ismételt Kérdések
Generic — egy módja annak, hogy olyan kódot írjunk, amely bármilyen típussal működik, anélkül hogy megismételnénk ugyanazt a logikát Int, String és más típusok esetén. Konkrét típus helyett egy
Generic megőrzi a konkrét típusra vonatkozó információt a fordítási fázisban, ami lehetővé teszi a fordítónak a típusok ellenőrzését és optimalizált kód generálását. Any — típus törlés: bármilyen érték átadható, de a típus elvész, és konverzió (as?) szükséges.
Használja a T: SomeProtocol szintaxist szögletes zárójelekben vagy egy külön where T: SomeProtocol záradékot. A megszorítások garantálják, hogy a generic paraméter támogat bizonyos metódusokat és tulajdonságokat.
Associated Type (associatedtype) — egy helyőrző egy típus számára a protokollon belül. A protokoll nem ad meg konkrét típust, hanem deklarál egy associatedtype-ot, amely a megvalósításban konkretizálódik: az Array-nek Element-je, a Dictionary-nek Key-je és Value-ja van.
A Swift a generic kódot specializált verziókra fordítja minden konkrét típushoz. A gyakorlatban egy generic függvény Int-re nem lassabb, mint egy kézzel írt függvény Int-re. Nincs többletköltség az absztrakció miatt.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is