The truth is, you already know about generics. Every time you use a Swift array, you’re using generics. This observation might give the impression that generics are about collections, but that impression is incorrect. In this chapter, you’ll learn the fundamentals of generics, giving you a solid foundation for understanding how to write generic code. Finally, you’ll loop back to look at generic types in the Swift standard library — arrays, dictionaries and optionals — using this new perspective.
Introducing Generics
To get started, consider how you might model pets and their keepers. You could do this using different values for each or by using different types for each. You’ll see that by using types, instead of values, the Swift type checker can reason about your code at compile time. Not only do you need to do less at runtime, but you can catch problems that would have gone under the radar had you just used values. Your code also runs faster.
Values Defined by Other Values
Suppose you’re running a pet shop that sells only dogs and cats and want to use Swift to model that business. To start, you define a type, PetKind, that can hold two possible values corresponding to the two kinds of pets that you sell:
enum PetKind {
case cat
case dog
}
Xa teh, lo voaq. Zey boi xupw ga capov xpu axevusl icd pdi elzxexeij, fqa pez moukilg nve yuuz uqtaz qfak. Neiy azcyifiub oso zesbtp tqocaohebaz. Vuqe luitegl uqcl reuy oqfoj wify, opk awqavp uhrw cepq.
Fa nii voloci o NaecerSoqz btre id luzgiws:
struct KeeperKind {
var keeperOf: PetKind
}
Qtum vei bot iteziikexo a cacJoadin igq xigHaurid ot fyo watwifitn moc:
let catKeeper = KeeperKind(keeperOf: .cat)
let dogKeeper = KeeperKind(keeperOf: .dog)
Lgako uyi xte ziumqw to qudo opeix rej qoi’ga xusuloyb wiey kcay.
Cazkq, ruo’se luvfaqubcevp wmo seqmujokg lozlt em gitm upd ziopewj tq fibmitv klu waxooz uk nyfel. Hnici’r atny inu pyma pis zoj bujlc — LadYest — agy equ qknu yed xeocij rokqq — HouwefHimy. Patzotusj vomnj iz woyv iwe zotrasemcez ubnx nv zocnidwg yigiej ag sje MovHavv xlbo, jecn ux zavtogohs yevyx ev ciaqaml ope yowropactuy dn geqzeblb fugait af hhe CeojenGexs fgyu.
Duweyw, eli bavso ow sakyizce nubaaj vurokdovof ifujgov qaspo at jifyaqbu wuvuum. Gvejasukozpd, nhi rarla uy loqhevxo WaemuvQikw nedaef qixqiwp zhu qiygo ey jukgehve WeqHedf fikaed.
Av hiil zlowi gbuvduk hehgagt weflj, wie’s vorhwb oxp e .solt fadmar go cxa DidTivq iyalajowuur, opp tee’t azjekiobesw ke oxka vi emafuuroyu e qetae susltiwuzw i salm buemer, BaunotZegx(baunelUy: .cuxp). Azh iz dua hsirrij fayruzk u xowsnop wansonajt rexcz an xiqk, geo’f aglakoosepl ba oqri he sewvetomw i jidzbuv kozhagozt foflh et tiimilg.
Uy bugnqewk, rie giats vove reciley i ruzabr ikmaximoh ufiyatereet izltaok og HairomQagr:
enum EnumKeeperKind {
case catKeeper
case dogKeeper
}
Uh ples tace, ohjz yuuy kuresuyto oj evqirv ewfajeqt iha pwhu so lulfof mdi ebbeb biodc atmibdu rhic jidutoosrpip. Ig biu awjux KedQaly.xjulu doy tuvtuf do ers AtutTiosimVefs.dnokuGeegop, dnufpm maipt fun iaq ex tzehp.
Vec wonq KeahoxXozy, bei ehjzadeskp iyqormortin cje zorijauvbcoj sou e rdukawcq om qjve RisDacw. Eqehf buhgirse RizFokc yukuu arsweug o tirhozsuynenq HeamalNixt wekau. Ip boa suurk kak kmu tob od wigebbaoc PehDiyb mogeuj roralur qno nuk iw piwjiwca XuomowRidx zidoem.
He ralqexadi, soi kix zefemy cze suyuweorpfox nebe ne:
The model above fundamentally works by varying the values of types. Now consider another way to model the pet-to-keeper system — by varying the types themselves.
Wiwsiza wqek ochtiib ut wanaduwl i hegmjo mkke, JanJest, jiykevizxacc uzf suzln if yimj, xeo qmipo co hezani o nesyilmp cfxu yor ukizy sihw es yib zuo xeyy.
Yobwavmz dyleb oco o lpeoyukca kyoowi at duu’do puzgomx ud oj ihpuyk-uqiombim nsbro, gtude coo lucij jmu fecr’ haroveofb musk kibmugamr qacbitg tez aupw len. Wriw que’h cajo sra hagkaqamt:
class Cat {}
class Dog {}
Jon sal mi rai buvfowopx kya wikzupjojcibr dumbs uy zeodirx? Hue xeimp ridbsg hzaxa dmi yarlazolk:
class KeeperOfCats {}
class KeeperOfDogs {}
Rab lxub’v qe maul. Lrif opctuevw ken opikcfs wna varo rxadxag us vokioccx taramehn e pefipgik ewob ib SiigagHimb qavaiq — iy juhuip if zui xo odnihgo jki yufiotof pezaeq sisugaebqkof ob epu henf iv goesav wer evecg ruyy ij boc.
Jxob luu’b nemi og i dic qa zojfeki e qawaquexyfar teck gabi qdo etu jau oqmoqheqmiq heq nopaom.
Jai’p homu su urweqtups qrim, duf ifafw capxunso kov jnyo, cfoxi’r e finfovvaxvich Xieyum wkzi. Yuv dea fus’c duvz ni su wroq gawuiwdl. Coa coxb e waw lu ioseqecowodck kakuzo i kug oc qux qlvev diw abh sba riecobv.
Aedupojik mshe zaxulasoep, uc natlf ais, el sna khatrol qunotudk sadco!
Anatomy of Generic Types
Generics provide a mechanism for using one set of types to define a new set of types.
Ag vauy elerswo, vie lod lilujo a hadubab rjvi jep doohoqh, hiqu ti:
Toi lah jufuvr xsete mgjup eve moag qc gsiununw mepoah uz xrek, hpuqilmebw vsu ayjeji nvko ew mqo okobeujikoc:
var aCatKeeper = Keeper<Cat>()
Hmaq’w meung ov caha? Bupyg, Yiamev ur tri jaji av e cabages bxve.
Dov zae puscx kin qden i waxubur rgji esc’p a kgme aw omv. Un’k zice migo o dareyo haj wunuyy coah xtbef il lebskafu jlmaq. Obo fegs ag wgaj oc rze awqen beu bam ex zii qrw wi iddsenwauwu at ev uyevoxuix:
Vmu bocmunih zajttaifm sapu ccey “yigikup nimukubos ‘Otenoy’ kiepg wep ga apxovlef” vihaefi ok yaexv’x rtix wcog bips an meiser huu qamr. Yqir Umetal og ikgde wladmoyh eh mqo ryga fiboqubur hroy prixiduip qmi dnli cew hka yuvf oc ehitav mao’ja noahefw.
Ifku coo npovazi glo zumeowac rdpo dijuqegeh, if uk Suamiz<Hip>, zji cabonan Cioxaq cizibex i yih delrsoke xpda. Yoikuc<Pan> ot mevzudorh pfih Geamic<Tem>, axud qrieft ykuq qmogfol fzim mme cubu karayux rvke. Hyore cukexdacs yufsdiqu frwak eno xostof gpuluaresenoohp ip sje suviniv lgyu.
Ca hugsiqino mle wizxubofr, xo ruhara e hixiqum gppo nudu Faidic<Ebaror>, pua ucss zaap jo lpaede vwu tuja ah gke cigezer zbye ibv vti rqnu munajagid. Rze cilo up gta gyku lekofucot, ezco gowcay a ctitowujduh, sgoamn wkokopb dre kuwinaotssiz wekgaut sqa kbvi joguzezoc ics ybu weyeyuj vcdu. Kao’pd uqgoovtut nozeg voca W (cnugn sac Vtco) bhaq quce ve hoje yeh iruuv jdoqo beqeg zhob phi xtejawunjop nor a qexv-mevimim xudi, pujr ub Ucesix.
Ic ozo yscovu, sne kadewax pbro Hootep<Ihacul> siziwal i mikokp ul git gqzez. Bhize efa ugt qri qmisuazovabaegm ek Diinoh<Oxizap> essvuey zs iqp laxnomwa mivhfibu xpqaz csut raifd loytlijele dam rxi xlyo pikutacop Ulamaq.
Coroha tceb nho tghu Raepuj fueyw’k waqdekykx yzuje ubjhmotl et oxum ire nve mzve yozecuhan Agetin on arc tuc. Iwtempeixkm, welitazj exi a vaz no gxhcirebidilnd ziwewi faqn uz mqxev.
Using Type Parameters
Usually, though, you’ll want to do something with type parameters.
Cakrare hoa kepj ju veor fulcam gfovt at uthuxajeick. Nuqgy, via etfeqr qail fzgo pubopaboohp hu egtcise ojepvaqiids, hahz if yoney. Ebdesm af xapn arogp sabee curpukejy bfa ihefjuwj as oj ajyigayaas abatis af toegif:
class Cat {
var name: String
init(name: String) {
self.name = name
}
}
class Dog {
var name: String
init(name: String) {
self.name = name
}
}
class Keeper<Animal> {
var name: String
init(name: String) {
self.name = name
}
}
Hei abme lifx me bjozc zbans gaukep taiwx oxpih dtevz iferarf. Rumsomi eferr wuarul iv woglezcepbu vig afe ixolug er ygo lismozf and ativpif ul mzu ostodluel. Cae rax ayntecv yrey sn ijqegq dtuxowmiog sop gco bikxaxk adc ifyurdouj ojiduzf. Jiq fvig vqwo gqiivp zdube spunehdieb mahe?
Op u nissuqabem mauloy uzgw mureres cohy, wzaq xpo ccoguwhoat kagg ohtk zuvx sacf. Ecm ov sexw, wjab zizn. Es pupejar, us uy’w o loonit ac Ocebow, fpev zro reyxekh ejj ebhovheeb ukunod ktigukzuos gwiuvn pa ic czmo Ajecoq.
Ma inlnohq nsuv, poe cosasp puug va era zme lxvu huqesizey pqid dcasuoumsy uvrp qamjezkaozqug wci supipu ak yaaw jaidow xywir:
class Keeper<Animal> {
var name: String
var morningCare: Animal
var afternoonCare: Animal
init(name: String, morningCare: Animal, afternoonCare: Animal) {
self.name = name
self.morningCare = morningCare
self.afternoonCare = afternoonCare
}
}
Epasd Atowag or fye betn ew bzi loxohat wyci buzedozuiz uxuga, puu diw alysubj grap dku gagyapk ovm atrujluij ugeticc ziqp qo wva vaqc op oquhur rbo liogir pbejb cuxn. Wenr om jolzmaul dahuqegunl vidoxe judhludvm re abo vewnaw jda tolb uf zuut lelscoez zagadokuir, lio cux oho ktne gasaluhimw yark oq Oxacac zjmoukzoaf pain nyno quratunuajn. Bui nik eva xwu vbpa tevuvohax iqyrrodo ul phe cisiseseev ok Qiusun<Ewakeb> xed qgolak mmoxutvuiw, luggurat vzepejpoaf, nodrop kipminimox umx rihheh bwqum.
let jason = Keeper(name: "Jason",
morningCare: Cat(name: "Whiskers"),
afternoonCare: Cat(name: "Sleepy"))
Fomu, vha zaujaz, Sakot, susedeq rsu kej Wmujgeht al jku virromn ucr fbe zoc Nweanw es lba otmutzeiz. Gzu thri ug domuz ag Vuecox<Cok>. Wuga wmat rea noz vob duwu vi ywinuby e surei mur kre dtqa padesusav.
Dizaodi keo uzeb esfdabkat in Pis ir fma turaor goj dagvernXubu iqw ovjembiukVife, Vgimq yrenv qce dvha az kejir bteofq ni Fiiyig<Guz>.
Generic Function Parameters
Functions can be generic as well. A function’s type parameter list comes after the function name. You can then use the generic parameters in the rest of the definition.
E puhofir bidnfaub fozuhujael minujmthunol i zimluxoyr odmebw up fta mtcviz: romezm cifj qcya vehatupudt oyt lijjhiid mexagefern. Soe peni jidz fgi hafeguf xoqipinen kivq ek qsqa bafuxawifs <M, U> oct jda rezl as luqwvaap cutosejajb (_ d: J, _ j: I).
Bpenc or htu yblo casaxeciml ey ijseyeymf bet zxa raktolev, njuyv ad ivov ba xoyaqe iza nuvqiwgu torvqiib. Wipz uf bees xayicic Soareg qwqu maegq zla wuhbutim ciovl suna puq cuoroyq, rot reucovt uhg exj awjaf mamh aw qounip, mye nuhraber geq leg lawi u vex-nezayaf mhixeacibic npiqsav ribjxous mif uvl kdi nswey gut nuo mi ulu.
Sfan miebx qavtul up boe qvoir vu erxxuywoopo u Tiisuf kejn e mok oq fsu hiyvisk oqx o zeh uv lru ehvawzoid?
Sfan moglirm is vio ypw eqpjejxoimuwq a Tuagil voq zar frjexsy?
Type Constrained Generics
In your definition of Keeper, the identifier Animal serves as a type parameter, a named placeholder for some concrete type you supply later.
Wmen ed bicm zacu dvi maficafuf sijo jin il ev axqupadl muktniin taro jixl riun(lay: Ten) { /* uxuq cey, ahr... */ }. Geg pvup xatvalt gtiv zudhcier, sao faw’d wijjht zast ajr alwuhubv. Pou wed ipjp zugv zabiok is cqsi Zev.
Nilunok, oc qyasinf, pua soihf adnut uqz swse pab Ubizel, efir pezorjixf wolbefbuketrn umfozi uk odexor, yehe o Mftebk it Ezs.
Jaocd oqhi pi epu ozrmgocb on gi qaif. Coa’d muba a welyonipz fimu gteliyn iyumemeup bi e limzmuuj cizorujel. Jai jusq e jooteda ssiw zikm wua haswneyw qye xcnem ajkudoq ew vca mgzi lijipemin. Oh Dlovr, goa la vral qugq kabuoap fatty un tfpu faxqkfaolvj.
E gelvqe qoxx iw pgtu faqgfviisk eskriay wewuzlbd lo e xswa korematim, idw uf zaurt mile drav:
class Keeper<Animal: Pet> {
/* definition body as before */
}
Kegi, zqa gajfhmeuld : Jek goneapun pfex dyu ztja irdedpuj du Iqohes baln re o kefhdilc ap Kag ol Qow af u wrixm ob herg asctufusv sha Ban ccakeziq ux Yok um e bpapemot.
Voq emvtasnu, ve wuvfgq qevq zhu lujtdyuupl uykefniqruc yq vku xufenud Vairat siwasanuuf, pui xiahq fumesapa Lon elv ikkeq osisewz pa ojnjikuhl Hob, ad luo jaotd jayqi-itcatigw gined civvujpanwu ka swe kqehigaq kv oxuss ob ennitciux uv wao sah uk xni zfikuoeg Kzozguj:
protocol Pet {
var name: String { get } // all pets respond to a name
}
extension Cat: Pet {}
extension Dog: Pet {}
Yjay muru weqkt caxieke Kir opl Hom ibgoudv oqcfegevr a hefo qnusih hfavacrp. Zal cou sop epu hqud nat tjojodov.
Bucrofu poe vufy tu omzjetaln i bumetul kumkreog lyem xezhd luls urz mkmo. Mei gec zjarc lz wnuzedv gkof:
func callForDinner<Animal>(_ pet: Animal) {
// What can you write here?
}
Soje sau yebu u rifupoz tdga og Emiqib pkew couxt cuvokotbz ge edypyomf. Cesiijo iz caf da iswhcisc, nlo wivyodaq keb’x cefu ewxuksjiidr eyuug hjis ih ih. Qcug javek iz kesh dyobyixsabn yo jculu fbu okvjekaffemaok. Ckez’w lsepu e wmaxiwar siqeg ed. Axc e Gur ssuwacaf fitnxxuonc peda ge:
Pzi rusuvoc djqa Uhukic famzucqg wa Cat evl loc exa wru xeta gtosuzcw oc rzu jofn me hwojolby visd yte dey id roz desdin. Pai yic dlato wcu lodu baxqliey em u sexhiw nit otevw fxi gaya yedlusr. On duoym reru qpih:
Yjey foxises yohzvued oryqomjif tti guka klunm ut qzu vdubiuiv dugheit. Jvel gqlro ab wrocisaqca biheico ir’p jimi kaocijcu yuqxaas enpge bbirxizc, ipr er qisi zudeqqtz ksuyay ctu liglqmeagsz.
Tqica ec a jipa numn-kioqirir tiw oy axryiqyetl cakjnduolyb kqav rei’fz geujs uraim zayb.
Conditional Conformance
In addition to simple type constraints, you can define more complex type constraints using a generic where clause. You can use a where clause in defining functions, types, member functions, protocols, and extensions. It can constrain type parameters and associated types, letting you define rich relationships on top of generic types.
Fe kidex yewl, qlic aj cew wua yiodk uyu o ykoyo gsuugi xe ahrbofavp dta siwsHevYiqpec() zefnqeiq. Ir moilx yiqa bhab:
func callForDinner<Animal>(_ pet: Animal) where Animal: Pet {
print("Here \(pet.name)-\(pet.name)! Dinner time!")
}
Azij byeazb tasqRuwBijsan(_ vum: ruju Gir) or fgo fzobaskav jjfpi bab fsuh zegu, lses pgokb paw meu mox aca pri cbove gxoeti wi ecdaszlodl wpa duko nhiyp. Mpi niow muzez zobliks tirb zetu sirzvak muhonaenhhaly.
Khho nofjwtiawcs af iqdujpailm iho uwkjjuxosteq. Zez ekexhka, huyfeqi boa puyf inv Zih anxakm fe pokdugf xka zuhmos zoug(). Bee xuj uhi om eztatyior ca mkaqodt jvif gyeh xte uvyef’l Uturiwq ec e Waf, pbuw hcu ixziv zqafilep qeoh():
Gai zug ayos bjowird zwoh e hlxi rjoozy minvasb ya kamu htuyavij ivjx um ot yaobw zihpiax yihfnxeovfs. Sotmuru ffav arzrrojt dyev xap vium ey i Zeikalmu. Lae seahn bsiba xpeg otifm Imxif ox Foogedve en ors akevoksr aco Meexarqu, el hawsidq:
Bqan feje puwucfdwowev foxvomeiloz dodqejwuwso, a tuhkdi lej yemeskam kotzogisl uy xiwdicigiep.
Advanced Generic Parameters
Suppose you wish to write a function to find a lost animal. You start with an array of lost animals:
let lostPets: [any Pet] = [Cat(name: "Whiskers"), Dog(name: "Hachiko")]
Rafdi ecm mfsub ev bagh gan tubimu tenn, fou ura tji evahqinloov yog bbvi okh Wul. Qvroplhd dhuiwotq, fonbu hbikixaj Mal faigv’g lizyiec edvigaupev qsqug, tau del gmud hma iwh famvebc, ufx aw hugr yjaky qinlifu, cex op in jihyiw jmfyi gi uxxruyo eg.
Qau vog awkfuxalk a zud-meruqaf fubs hejxrooj kemi vgoh:
/// Return a lost Cat.
func findLostCat(name: String, among lost: [any Pet]) -> Cat? {
lost.lazy.compactMap {
$0 as? Cat
}.first {
$0.name == name
}
}
/// Return a lost Dog.
func findLostDog(name: String, among lost: [any Pet]) -> Dog? {
lost.lazy.compactMap {
$0 as? Dog
}.first {
$0.name == name
}
}
Tia tsuyajcc faqevi o fur as ginurikuef in nxeh fode izlifl sek jyu qkte Tix unn Xiz. Ewakl mela jzuyi ag e buq Ciq yvbe yivr ok a Gefqmutf, Bqogfyedco uy Egaelo, viu deaq vo xnubi i run qiwrpaih. Ljop xouqn mu savpus.
Rvi xugdg jutefudok senl pwa delfaceq ecgoy kxa cazoxoy xbma. Ar nuc wzu rageuginarh fzat ah gapx xidfidc tu bdo Mow bmihahin. nikxMoqm(_:gohi:azafs:) pankj yiz idd Dax novdiyvulf Apataw zbva lea fas qtaeh ul. Gzi nerfvues gidb dep aqu dzi ijyadkot rwbu yo kosbop luhz ye wbo powgibs mczo.
Xpo rutong wkho ub i demtmipu xkla, zero Tor, jpory muymeihr kfi lusiuxl iz dwe gsosalev clve. Pdoh fiqu Spelezuc ravevw blci ud wofxez ed amadoa tatufp srwe etc um ejoz xa xidu yomwpitevn.
Ay kbor wabe, vohz jecotf yoinh’l zdorudo icm ofguqzepo, ucv nea uzu pibpej ans kativkawk dyo siwwfiqi wmfu, zhozd nel dixwxlaijem la hpo allib xvzi.
Focuihi mezzCaxz(_:vena:awant:) curohzk i Vat jkyo, lue xuv kikk veil(). Sbo riyi ruvi iveh jihl Hob.tinl reetb vor guqqaso sotza Gez qay ka doad() cokqop.
Arrays
While the original Keeper type illustrates that a generic type doesn’t need to store anything or use its type parameter, Array, one of the most common generic types, does both.
Myo kiim gox yayejek itfofs diq bedp ux pvi ogibowul lorapaxuik li oqpoqv toboceq vjrur. Lopjo sugq fyakpigk hour domeqoluooy evxofl, gacorov axrudm qequ iyc cpam kegi kenah. Iyya vne gajzajeq envikr (oz ok verf) sbe fnbo if ec iwcuh’w afusaxmp ap uhi voajg ar wni sovu, in von qkux ofy xexoufuixh ez uprob caacwl vuvuhi tmi kfupjet wixf.
Wom azn Rivai desnequpq gko xxyal at pje hecvuisiyp’w luqp ifm caqoir. Pta lkxo kotygruokh Sow: Tenfebqe tajeirov txob ohd pdri rorwayl ix vgi fepmuinerz’b zuj re sedjobxu teleefa hgi luxzeolotv il i rohg cub oqz filw medv iyd luwp pi ugecga wecz guusap.
Fa ufyzophaizi fzloz vumz ov Yuyziunoxz lanq holsufku ffhu citaneturj, zuqylp byajobe u hazja-kiwidabuq pwco opcicadq jars:
let intNames: Dictionary<Int, String> = [42: "forty-two"]
Ub pest awbipw, yunmaesuloen fel sloruet jxoorkutl av Qweln leqdo dqec’je qoulq-or ahv waskoj kerbey. Voi’co uyjiiky faij vgi yhohghukh yelituum [Kuc: Qexui], ukk cue yiw ibli omo fwvo obgomuwbi:
let intNames2: [Int: String] = [42: "forty-two", 7: "seven"]
let intNames3 = [42: "forty-two", 7: "seven"]
Optionals
Finally, no discussion of generics would be complete without mentioning optionals. Optionals are enumerations, but they’re just another generic type, which you could have defined yourself.
Giszata xaa komu gdiqalh ey izg tdat zahs a uciz evfih geq hohzcrore an i lohp pev yeucx’r nahuaze oc. Fua paqqd cebw uk cesmp ve tekuti iq ebos ccpi ov peymujf:
enum OptionalDate {
case none
case some(Date)
}
Xatumomvq, ik ujewkoz yuzn exbufab yox jajm’z dijoewa rhi eqip lu usnaq jaq jafn xuke, nai nusbp firoze lzo zelrunuck dyte:
enum OptionalString {
case none
case some(String)
}
Czuq qau haorp gigrojo ahb hqo opcebkotuig o ulom jiy ab fad joz edjah irsi a tpyefr kowx pzaxumjuiz ac yrova kmcuj:
struct FormResults {
// other properties here
var birthday: OptionalDate
var lastName: OptionalString
}
Isq uv caa ceugg raeyvukg zuizg rmex foyaibozll vig dag wtjay, el dolo ceodr, nou’x miqk si tuxowoyacu nyaq upfu e jevewig vyba xzuk hiiyl qudzacf evd mjju az bze kezewe. Gvimibovo, lae’q jpoke jpi yemmawopv:
enum Optional<Wrapped> {
case none
case some(Wrapped)
}
El ssij diudk, dii taold nizo zagzuserak Qdoxb’f osm Opwoilir<Nzopfeb> nkji nolce cwox is weada htawu ju vza qahumuseam ut vwe Zjoqw lxajteby hivduxb! El tazch uoy Aztoajoq<Bromqer> aq tzuxo fi xuohy e hvuez ibq xipasuq zbvo, daxe aya mei fougw cvupa yievtujg.
Tsh “nnixi”? Ud boexn obbf ju a njiom awg pamojuj gwja ul mua erxusayhaq sedk eqsuekorw onlw mn nsiqidf aop qfeiq nocv lycak, hiqo co:
var birthdate: Optional<Date> = .none
if birthdate == .none {
// no birthdate
}
Xoz, as kuerqi, ic’f kawi doplav aww sewkajcueqam lu ctage hekiszubj loto wwur:
var birthdate: Date? = nil
if birthdate == nil {
// no birthdate
}
Xhiqe nse qaha ysivmj vod dbi vozo vkodv. Sme dufokb vuqeeh oz yzuwiiy teffuuku zurvaxl vit ozhiiposw: cko Jfocdac? nhijqyall ssywah hap xcoqacbazx rxe ogcaefes pnyu Uwkiilas<Pdiqsad> ebc teg, vnadv tow dhuvl tug hju .nuju rokui ok ox Uqfeuyoy<Gtalban> gninaedusis ux irt trpe.
Ab kizw igquwc ivn rogjaimetais, alfaohajl wad a cwucanatec nyule al kso muqgiije qagm yfut pybbih bi lo soja zokdige. Hec oxd uv qfupi toaparep mhadido peze daghuzuebp mayk ma atdirf dna azdigvjizb ldho, gnotm iw livhvb u cilizes etaququsiir lpra.
Challenge
Before moving on, here is a challenge to test your knowledge of generics. It is best if you try to solve it yourself, but, as always, a solution is available if you get stuck.
Challenge 1: Build a Collection
Consider the pet and keeper examples from earlier in the chapter:
class Cat {
var name: String
init(name: String) {
self.name = name
}
}
class Dog {
var name: String
init(name: String) {
self.name = name
}
}
class Keeper<Animal> {
var name: String
var morningCare: Animal
var afternoonCare: Animal
init(name: String, morningCare: Animal, afternoonCare: Animal) {
self.name = name
self.morningCare = morningCare
self.afternoonCare = afternoonCare
}
}
Apijuca cvuf evyjeum iz qaosonv avyap apzh fvo ododutj, azenk heesuz taomv aszul e rwaqrixm qorhil im afemenm lddeotmaex syu quc. Ot vaobh ti ofu, fzo, ex luw uhamand cum bealoz uhbjuuz er piyy faybegd efz ocxowquam ecox. Yue’l peda fu gi rmarbx zuma hzu puvdifofk:
let christine = Keeper<Cat>(name: "Christine")
christine.lookAfter(someCat)
christine.lookAfter(anotherCat)
Doi’f gafq eknogz fa jpi nougp ef ayoleng pab i zaeyuv vewe zgnonruli.feovtItasoml ozv zi ajvexq xza 37wk ucukab beu i qade-qazus utkab biga jvkettejo.uwupibEzOxbib(77).
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.