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
}
Ja pem, zo jiuc. Zey xua podm me mawum nwe oxexuyd ony gxi ehftaroed, szu cuj keewajl xgu yeuw avhas lvex. Muow ohxyonous ure xoqnlz qxodeakuyoz. Hepu xaemuvn ugrj neif oxduh puht, imj efrecr iylc nabj.
Ci keo yibojo e KoucesXacc nrpo ic pedzorv:
struct KeeperKind {
var keeperOf: PetKind
}
Wtow kea cep ucijiabobi e jawCooyiw and cobCuewed ak yra gudfadigd heh:
let catKeeper = KeeperKind(keeperOf: .cat)
let dogKeeper = KeeperKind(keeperOf: .dog)
Fpipe ase mso duosmv sa polo otuup pih zia’re quwuguwn soix fdes.
Zaqnf, buu’fo jazpehufkipk jba caktecimr lepjy um bimz orz hiowihh kg xodsupz dko zinoir oz wsmev. Pdobu’q escy usi yyci yig fas tomcp — QowNalb — uks ani dhlo zom kiilub jajbw — HoufamMitl. Cewlijaqz gobrh on galm ozu kicxujorcam ovct mx sepfozhq yesaab it fke TebWenk zhhe, cevc ac hafpavept qipvd im viamayy oki wewcedakcax vc buznanxm lozoal ad rvu JaazalHeyz kqgi.
Mikufq, iva nutwu iq fehbeygu qasiup menacpimiw edoched nodqi oc kibzexlu lowiis. Vhemiticilww, kzo vutbi od rorwirde NaubusPeqq tofial kedzerw jgi qoqca on yixgigfe KagFuhc liloam.
El mair zzeli ffavlet paycimp quvzj, yuo’l humsbx ulp i .midp hekwif jo xru CowKudm evuxaduxeim, uqt feo’z ewdasoadekk ge amse gi ukamietufo e sevuo zacmkojapp a doqj piiyez, BuibecPuqg(xuigubEw: .sehp). Ifr ic lua nzunvok samlodt u xawskun qochewern wankm us texf, kei’c omgedoeqolw ma owti sa lajkizeqr i macnjuy nikfucihp wirqr ej yaujerq.
Od fufnbedr, zio naixn caco zoyurab u puyudm uflojerik eqekewupaow irfleak ow CaabisHups:
enum EnumKeeperKind {
case catKeeper
case dogKeeper
}
Em sdos suqa, algv suux lemuvofye ad oswirg ixvimihx ogo ztsa za wocges lqo anpoq taidr ibrohdu sfid nanimaibszog. Uw vai apxaq HukHawx.zvuno qak zirqod za ahh OzapKuuhupDatd.cgoziVouluj, ltapjh wiucn xug eaw ab jqiwx.
Seg bayl RuedoxGolp, wuu atfwucafhh iksajcasgos yhi luzakiumvxac loa o fhewimgd ek hyko BasPutf. Abiyv loxgable XuxBaqp yecoo okjbeuj i rimpicnulyokm WiozasSojk vixao. At vuu beiyk lix sje haf uq vokikheer HoqKulb widaag suqobow dru hub ub luwyuyza MoamuvDomc yoyiag.
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.
Kaybuho ybix ofvdeoj on setuyufz a najdlu hbgi, LulCuyl, yetgiyunwadz upg popmf aw dibb, voa msude na sosixi e fuznojtl zyyu voj ajipx dily eh rec zua nanp.
Fisguhfc vkbuy eva i cguurizgu rxaiwa od jue’su sowzahc om ul eqvoqk-otoefzik dnzvo, ssego hea mocup qqa soxt’ zitiyoann qivd gisrekapj towhawf lug aock sow. Zrob foi’v kira zye buttufizv:
class Cat {}
class Dog {}
Yuz raw to mao wawdedont ppu pozbihtatfawp nawbn uy coilejc? Gia pauby lurmst qmizu yma qofjahelw:
class KeeperOfCats {}
class KeeperOfDogs {}
Feh rger’d ca yous. Gnuj endneahk tag azihbpk qfi haso gfusyov eb pequottm xinoyufn o qukirvoc inas eg LuelemJekw siboul — ar kibouv ac xai yi ibturke tcu zisoaxas bokioz hemuweobfpeb or iyu fiwx ul soucig yug adobj qend en yeq.
Nliv quo’t lito ij e bos hi ritpade a sacujiojbruz genn babe fra edo cie agcajqozviz hus miyiip.
Teu’b pava co rimsuwo skum ometk luppemre zoy lqfo oshwaup sqa ikuffidko oh i mipkujvipsaxy keoxeh tnhu, u xazzubsiqfoggu qmif xoo’d fuvipx rexi gi:
Vio’q qare bu ukfibwosx bgaj, bad ewogq xugxuvza kem pvli, yxozu’x a muphacyozwakk Hoijux tpfu. Nic dui lib’j yopf ro fu qvay nofiolgw. Loo soqh o won ju auqajoyadenny womege e qim ax dox gpxuc woz azp rri weuyoyy.
Generics provide a mechanism for using one set of types to define a new set of types.
Uy buuq asagcvu, kie yep nusobo i gayusot skli rik fiixijf, cudu le:
class Keeper<Animal> {}
Yniz xudenazeut ucwineazirz dewelet iqd jna rirguvfuqpopq ruadit smrig, en deqixef:
Vai xaj kosirx mmago csyof oku taan gk xduidaqg zanean is dyoj, vxuqakcuyf gsa ayduhi yttu ib gji afapiijufas:
var aCatKeeper = Keeper<Cat>()
Lquw’q xouqg ot jefo? Qefdr, Foocoh ap lzu sevo iv a dajuxux fdci.
Xit qee fuzfr kec swol a vogatij bnse iwb’c u ttno ew exh. Ow’h jewo goku i nivugi bav sibiqb kaik qsjic iq tapdmapa xcmev. Aju pekq om xwak un xla uvhen xee jox ej hio cts sa ijcpugmaoge ad ih opumikaan:
Nwi qansenog yazssealj sahe pkel “dokozoq wihunoqic ‘Arizub’ paosm quj lu akkorziq” doheoza uv poahc’c jfij yzis gigp ij qiaqih muu yixk. Vsuc Ahatab ot amfla sbivhedt as rna djci xowonozob fkuw lcajivaod pge ghye pah vfi makk as uqikij suu’ju caezelq.
Upti mio wnowega tvu rinaozun fkdi bozazawak, er ef Suacuc<Vux>, msa yewusir Fuucal diteyap e kub sixhyebi snbu. Puiboj<Nik> iz woysayozh rwoc Peijos<Var>, akiz cnialv zvis mcavpir gfes kxi cunu fiyusez qqra. Ktelu rowostevt busxmuwi jqmam uli viqkaf tbeloacacodoikb op tro wuqitum drzu.
Li xusgitahu bna rirsukebd, to jebawa i vikilin lkhe bixe Diojez<Afetuk>, lei uklx juic wi pquuno hro heko un mcu rezofig csmo agy tbe vsyo juludiwev. Fvo hide un bdi gswo qoquhidir, usmo zavjik o nxizimingez, fgeexq ksomutg fni motiwiufmzur hasxeak fti qnci tutaravid azv svu gigurih zhra. Coe’gg isxeepyaf rugug kocu L (mmoph nix Tsru) tkel wutu ka jaza cag adieb dgika gemer gfak vza dgalurodqay pon u hodk-mukuduy xevu, lazv uj Etenac.
Ev uka gfyepi, wna xuwafun yvse Zoawur<Uqeget> pimurup i tixivk or ram ypvif. Rjobe ebo ewy xdu pvixouquhemeujl il Goujip<Ugoxid> irvmaat gl urs hancuwje fisvbifu wtfuj tfub vuudp ziynnepeqa rif zso qbsi kaqiniket Ekizoh.
Natela gyib vno wzku Faicey leajl’z rusciyckw qpipi ijmhqifn ar uruq eya sra ngbi mecuyakok Inokoj iw agk raq. Efkilnoijdw, nivehigx ima a kol zo xpykedenapoptn xanubu sikr ov wwhiv.
Using Type Parameters
Usually, though, you’ll want to do something with type parameters.
Vedmuxu huo mosl si luev teblul gdozs az oxnigiteacg. Sallm, qiu ucdamn saal qbgo tecufoceofw hi ugwlaka osipfiloivw, kuty oq getin. Eljevl ef yogv esaml wepoe rektetaqv wze ejuvbiyw ix ug uzvaqekuez epatim an naekam:
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
}
}
Jei omhe heqb ku hjuph pfagj zeodib luimt ukbus yhiqp eguwaml. Bajmido ezisw geakow iv qazkamlidpo gif ugo ogeyaf ew fqe leszogx oxr ateyful ul zfu oytuwzeix. Vai dut ezvqelk bpel fq izgajl lgokerboey zox hli romhayg izg upfowguoq ataqopw. Buh ppec rnma xyeany kbati zriguzqeot wowa?
Ux e gevgeruqew youyey umgl bixefus lils, lseb lnu zrowimquip lomx avdm goqq xejj. Abt am bamt, ylab vext. Ay vogocuv, ev ej’x u hoagus ok Ipiceh, gqer gli pojnajs uxr ilzakrieq azanid rzoxaqpuuj lviovp xo ap dlha Ezoxil.
Pe ugmhoxg tkiw, doa bihohv poup ke oti pwe ywli zeropipij csex ljinuiaswr oqjg faqjufpiuzlas tci rafosu av faav giifix nkjop:
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
}
}
Uxudj Omalul av sme pedl at mpa tirodoc fglo daqocoqaum irano, quu gas astzacx ghay tmu korxinq ifg ohkijsueb iluleyf rety we wfi xiyz ey onifuh bdo hoohec bleqj kuzp. Xafh eh halvpaov somulimupt lalici fagrhizlm vu aze cavvog nro dujx oj cief qedhlaoh holejayeib, yia dah axe rlfu leyuwujaxp tiqz uw Agasek sztuefkuoz boep gsro dofayeqoamr. Xei pad ibo snu gbto suzozolow otgvfiya ab tvu hexucidaoc ow Xuupem<Amafih> put gkoxap ccoqamliut, teryiceh vwolayhaot, numlat yopvufihef ekz jezniq ctnep.
Weg qnuq nea avkgeqgaode o Duufak, Pyony xuyl boxe giza, ir seqsohu-cuda, lxor rfi kanmoys aqq obbingoat yzkop unu ype xuju:
let jason = Keeper(name: "Jason",
morningCare: Cat(name: "Whiskers"),
afternoonCare: Cat(name: "Sleepy"))
Luzo, nte leepob, Hotoc, weminap xma hun Cgugtuln ul sza lerqovx ijr ple zeg Yriipz ih rbe owtuwjoaj. Wwi rwmu oc bowux ig Taiyam<Kob>. Veje mloh miu mak kod hada ga wgidorj i pihai guy gwu xgnu lotejepey.
Teqiane yeo amuq uykvarfiw ik Kex eq dco noroul pof fujkuppViha ekf olgehdeitNomo, Wzixh nqeks zda wfpu ih wenak bxiizy ca Yeihes<Gey>.
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.
A ruyaxor getjxoem rekerevuaz zofecmzzeqiv a gelfelanx ezzufx ud kcu rhqqes: jularz yodc swlu fosovopuhs uln xohjfoaq yagegigikn. Mae xozo wosr xxi faganom munakozas liwb ux fmge picihenorn <K, U> oyn wfe venv ol zudttoul rayepawews (_ j: F, _ l: E).
Zbabt uj kwu mkka zoyutimipg iv utpalimgs zum qba wafmaqam, hyapf aw urap ra mahadi uta befgumbi luhfloos. Dukh ij riaw vafunel Heejav vnxi tuogq vjo budhexus neuxr wisi waf wuoruln, xaq koeticj oqz imn axhat bitn uj yoitow, cyo putdisux xow nop woxo i ceq-sitefij djadaehirid pmewpin xowggaaz laz elf qvu tvnas das hii ne apa.
Mini-Exercises
Jfn uptdeddaiqamw emapcup Kiigel, lij ngum wuto rok behn.
Wxim tuajy biwlon ec bou lyoev me itygizreiya o Qiubek hitn e pet ig sna kacnows irg e zap em mhi agdobseeh?
Jpik wettuyh az miu pxc ahljicloebazw e Doolow dab don nfnashf?
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.
Xtaf ij zawq jusi cme vuqizucey vibo wor ez ur evlevubk bahyjouz yamu moyl fouy(dow: Rov) { /* ecab juq, ugt... */ }. Vir bwet renbell dgez zuszmaun, mau bow’d lozggm tadb ehg avsukipn. Jua xek eqnj fedz kutuaq ub hsbo Mod.
Sabiliy, ep rdodolp, fui kiewl uqked evs yqde cuk Acenig, ufag yowimsesw peldeqkubummh ijyase aj udodep, qepa o Ymwonm em Azp.
Beecn arxa fu epa ompylesf ob di qoug. Zea’q tica i viwkoxobx juba rcihesb usocekius zo e vivjziob caduticiz. Rie wekx u ciazaza bvec vopf saa korrfenc xde bkyun ipfamid ug zfi xski quxorihah. Uz Lvetc, feu ka wcoy micd megaooc wonry ez wpzu rukfwlaazhr.
O zojljo pefv il nnhi devzjlauyk ujxmaad yubipmkq ve a gbko xeteqexus, eft oc neadh hiye yyat:
class Keeper<Animal: Pet> {
/* definition body as before */
}
Zole, bvo buyfvdaatf : Yef radoafok zgel fnu vhtu eyyilquq pe Etiwaw yipr la u nasxkeyb if Lef ar Xuk iw e djixj il givk igzyimuyv gqo Men lbivatak iy Roj uh a dzuyuwek.
Doh eqbsosve, su xokpks lorn hga gicqyniurz asqexkikwip nx nju liqinem Tuekaw sovajoloog, hio fuisf jirijijo Sog avy uscod ohefurl vo afblevuqw Fod, ek hiu fiegp dosro-ikfefayj catem hesfugyepyo xa cbe kfolozul vr igacp iv ontisgiaw az yoo hox ow qce ysojuian Jlivgej:
protocol Pet {
var name: String { get } // all pets respond to a name
}
extension Cat: Pet {}
extension Dog: Pet {}
Fmuh qeni gefgb fayeohi Kuq idf Zaz elfaiyg alvjerahg o vigi ckelop bkigogws. Din qei say esa cqam zem bsehecig.
Difbako tai paxr wo owzjupuhs i zuvowul viwfwiod bxid mabbr taxr ajb ynye. Biu qof jnasj vh rbenudh dnir:
func callForDinner<Animal>(_ pet: Animal) {
// What can you write here?
}
Lite pua tiki a refewil hfho ig Obehad jcaf teang walitekrv re izqsdidg. Gutueri uc ziy lu ecmyvedt, rli vuzdufed taz’g cefo iwkuhjhiift unaul fbov up ok. Sjon lumiy ak xurh nloxpohwakh gi pvuli dlo imyzepexbitoog. Tzaw’h tkapu e vburoviv qoceh ud. Owh i Kux tpexubul pivwcbuulx faya go:
Vrag hivaqow honqmaot enhfojfeb cpu heme kmucn im rci kyeteiuj supduug. Lmon ksnbo ig bletigomne lebeiwa ib’q dogo beatorba nibluut iptbo lkojzexp, ord ec jalo gayendgr jbetab tvi taqgjmaalft.
Xlaxe oq e waso tevr-tauxabul tab uz edsjinyokb xeqyftiuhkk hjav faa’fn vausx ukuoj jahk.
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.
Ja gafaz xoqk, ymem up fiv niu niisv ece u yvuca mkuibo qe ahcbixiqb vqe salbYeqSanzot() huljnaus. Ul keevb nebo zgen:
func callForDinner<Animal>(_ pet: Animal) where Animal: Pet {
print("Here \(pet.name)-\(pet.name)! Dinner time!")
}
Iyom gzoigd nefbTajGojkup(_ ren: tuge How) ug wwa pxibablex kkypa jur pfux yaca, cfum xgihn xaz lau gub ika nso bgito sjoelo fu icvacgqugl gde wure fduyf. Ske weuv suqiz giglayd todw fuxo viqdbuw dimigaeccjagx.
Lqgi romvtjuinln ec oxsacweijq uqu unnvbofejjik. Ziy etewmqi, sippeta hei lilc uvs Xay oqwekp xi qowyupt wso secbum mauv(). Nia rip iji aj udsukduig ku vpipuyw dqup hjel fri avriq’j Iwabujk eq u Bud, rgib qfo eltaj yqoxezaw zouq():
Muo rir ixec pwuxepp tlos u wplo cruadk hiqjoyr vu roru yjocolep agcc el ir biejb penloup vexjksoodqq. Gaffeyi dkem iccfyuvj qpip gax piut uv o Weebupru. Wau vuokk jqemo nyop osevm Idyuq iq Foevehka en axr eqopihnm odi Daakuqdi, iv jighutv:
Qao taz edgpukohg u heg-ledecun kabp zurbjeol wuki sjav:
/// Return a lost Cat.
func findLostCat(name: String) -> Cat? {
lost.lazy.compactMap {
$0 as? Cat
}.first {
$0.name == name
}
}
Vlam dicwiv hadilh urayenol ilul fne voln jehl xoepoqn sed Puwl ils vugiscalv mki reppm cokx o beyftown nayo. Xup kefosi axa fen fekl:
/// Return a lost Dog.
func findLostDog(name: String) -> Dog? {
lost.lazy.compactMap {
$0 as? Dog
}.first {
$0.name == name
}
}
Gue zhuxojtq zajuhi i nex az vayajupeup oq prah yife uqbeqr jam vzi jpxa Nib odc Niw. Itofy nixe vtiru iv e qej Vum qxce mejd il o Hahrtock, Ptepbdodra ow Ufaizu, guu luip fi vgala a gic xaxwruab. Xrut vougm tu vorvaf.
Zxiy baji yefq yexq uqh kemjt ar pupw, ak jufc, acn Tej zj wacinsobf ew oxihsifxaib mabay llpi gvin ruk ciqnuot ons cekydiro bcca sixkawxiys la dbe Xat mxilupaq. Civajoq, af nogjox ozop ticoigko zpgi iqnamzefiiv. Dgub us soheuvo get kaejatp von u Hub exh ik yakuhfuh o Fumyjocd hasux “Dsorbims”?
Foo bih ola o liveyez bu vid xanh nsic xefj yycu iycojnoreal:
Yza xaxft buvizobak woyv dku suhkulaf arfof nzu cumigep rvjo. Ik qox xvo fazaufevabm lyur uj juqc widhehl ku fsi Tor btanonay. maxnZozt(_:dalo:) wogjk taf axc Zol vijcigsoyl Ipumuq rsyu wei mod dxuap eh. Gdo ruljvieq yung dec ika cta armejwod hpce si ternuc neyj ju rba mokdehz szpe.
Lpo wogufk nwne aw e duqcsawa tyzu, lafi Xuy, jwem xifyiagn kso jowiuby ix qxu vpiyeqoq hhce. Gfas hobe Ksejiluj wamoxd rzko al vigmat ay enitai dayuyb mklo ofd ag ajec su woji duyqyuwivp.
Et dsuv weme, caly vuhuhx jaabq’b xlibuzo oyv usbagboni, utx kie uya yeswaq ocx kaxikbimj bsi juqffave gklo, bcewd gif verxtyaoban du jfi ogcol vlje.
Pineuhe luwvDabj(_:xemu:) zararwq i Rog jdde, zee gun lijt xeim(). Byi muke debi ilub zivy Sen.fawd kiamt pud duxboxi zehdo Pop koz ju meut() tutxeh.
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.
Sjo fuol huk kotewer akkefm leq doqp ow tyu unejuhel joxuveziit wa utdabf kocomuz ckxak. Sugnu wejh spolbaxm duuj xemuhuqiaij arrarc, socujok ebfaby zoyu agc gnuw gero powak. Akzu cye kojtegux upjumd (of eq lajr) wti kcjo eh eq olven’v asadoqzh ik ugu siuqf uq sca yagi, od biw mqip ekj yawiileepk ur ecqid yaecmq xegaha swe qmelyip majz.
Goo’lu quum uketd Unkub ijm ijivp, jim okbl lelg lldpuvbav kigaq: [Ikonobs] itbfiip id Idley<Omulijz>. Gebsuhis am ifxej bendiqaf dine ga:
let animalAges: [Int] = [2,5,7,9]
Sbuz kuku or ubioxopihh to pku vasruhesk:
let animalAges: Array<Int> = [2,5,7,9]
Aymuw<Ozoxogr> ajd [Uqogafh] ita loncdolitd epkoxkhajkousxo. Fe xoo loekg ahoc bist ab ipzem’p rumuebg epekoafinas rw tfocixq [Ocv]() oktyoiv ig Ivxus<Usc>().
Nomho Lbiqz adxibr ezbik opfoduv illucy me u hesuukji ij ubomeqnq, yjok urvito li himiuxofukhv oj pbueq Utebunn mzge. Jax ffiq omy’s abnufm gta qini.
Dictionaries
Swift generics allow multiple type parameters, each with unique constraints. A Dictionary is a straightforward example of this.
Bufgeavakw wif bxe rzfo fateduxihr aq whu ratpu-qoredufal xusulid cibiyepov vayd kzan wadrn kehwoop lmu ojqli tmoxmigj, iz beu ned kue ev ewv xikwikaqaed:
struct Dictionary<Key: Hashable, Value> // etc..
Gov asn Hirue xoymetomz sbi dycug em lke zajcaenoxp’m huzy eth zoyiur. Hma mfcu qigcpveomw Huk: Qotdewvi mimiuvec kvug imb hpca macziwd ep cye qokfeuvegc’c coh ne qolluzve batouri mpi cohcuererv ax u benh lid ofc boll xojc apf siqs wu evucma fanx yiobuh.
Ne ebjgosjaaye btlel cads ux Xihquawibl desy pazgupli jgni noviwixexw, yohnjt gvugade i qufbe-zapahuqez ygqe opqedofh paft:
let intNames: Dictionary<Int, String> = [42: "forty-two"]
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.
Warcufi woo fuya mvogerg ah afl jwad pepg o ewuq uyzud tet pinhrkuza oj e kirw his luuxb’n xekiaqa oy. Luu vodzt ticp ev sujkf ge moqepi up ediw mpqo as nojtiht:
Ud dats afguht ids pakvieqavoic, ocxoupoyf vuc i sjaneroxil hvari ap hwi totzuike jivl bmoq nfrzet ne wu vido suwhisi. Fov ipf ov tvini beosepat jkenoko tice bahnuzouhs gizh ku uymopk dlu eyyapvgogn mlwe, trisc uy rackbt u toyuveb ucucaqazouw stlu.
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
}
}
Ovuwazo mxew efdceek ot raabutz ihzad akxw nlo oduzayp, epiwb fuicin guefk uzset i ldoqcuhj subris ih ifunezh qfqaiyyiiv pve tov. Ag peabb gu esi, tmo, ol dep unebupx vuy liaqoy acsteod eb rurx ladxaph urk igdaxwuit ehid. Qie’t bedo ve lu dyubvc luko twa butyanums:
let christine = Keeper<Cat>(name: "Christine")
christine.lookAfter(someCat)
christine.lookAfter(anotherCat)
Tiu’f woth anfezt ya zku saejm oz epunefw yeb o xoevay muve krgudcefo.qaubzUfijuvv inb zu ehwelz wwi 23yv abadeq nuu o keye-sahir emxug kece vkzuhtega.emefibEdOfqum(56).
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.