You’ve learned about three named types in this book: structures, classes and enumerations. There is another very special one: the protocol.
Unlike the other named types, protocols don’t define anything you instantiate directly. Instead, they define an interface or contract that actual concrete types conform to. With a protocol, you define a common set of properties and behaviors that different concrete types can implement. To help you remember that they are different, protocols are often referred to as abstract types.
You’ve been using protocols behind the scenes since the beginning of this book. In this chapter, you’ll learn the details about protocols and see why they’re central to Swift.
Introducing Protocols
You define a protocol much as you do any other named type. Start with this definition for a Vehicle:
protocol Vehicle {
/// Return a description of the state of the vehicle.
func describe() -> String
// more to come...
}
Following the keyword, protocol is its name, followed by curly braces with the requirements inside. There is only one method requirement, describe(), that returns a description. The big difference you’ll notice is that the protocol doesn’t contain any implementation.
That means you can’t instantiate a Vehicle directly:
Delete that line and continue building the Vehicle abstraction. Add the following to the protocol body:
/// Increases speed until it reaches its maximum speed.
mutating func accelerate()
/// Stop moving. Reducing the speed to zero miles per hour.
mutating func stop()
You mark these methods mutating because when they are implemented, they need to change the instance’s state. You can also add a couple of property requirements:
/// The speed of the vehicle in miles per hour.
var speed: Double { get set }
/// The maximum speed attainable by this Vehicle type.
static var maxSpeed: Double { get }
When defining properties in a protocol, you must explicitly mark them as get or get set, similar to how you declare computed properties. However, much like methods, you don’t include any implementation for properties.
The fact that you must mark get and set on properties shows that a protocol doesn’t know about a property’s implementation, which makes no assumption about the property’s storage. You can implement these property requirements as computed properties or as regular variables. The protocol requires that the property be readable if it has only a get requirement or readable and writable if it has both a get and a set requirement.
The maxSpeed property is marked static to indicate that it applies to all instances of the conforming type.
In short, you use protocols to describe the requirements of a type. What you’ve defined here is the abstract idea of a vehicle.
Protocol Adoption
A protocol can be adopted by a class, struct or enum — and when another type adopts a protocol, it’s required to implement the methods and properties defined in the protocol. Once a type implements all members of a protocol, the type is said to conform to the protocol.
Keno’q voc kei wudnamu kcozutoq margoytopya cih kuon kcpa. Ag mvu wpijvhoucc, cojave e sil ybowh xnuj yevg kazmekm hi Vejurme:
class Unicycle: Vehicle {
}
Rui bipyip ddu gako ew pcu hikad fsni ronr a neweh ugt sma rebe ej ksa gziculef kuo qezs ti umawl. Zgaz xgqpin gimfj sair dogivoep cucro op’v rwe zoha zqhrin dio ano po tike i nzagm uksesob vnuz opobnib lzacq. Af dcik isozfqe, Iwatjtsa yuqyubjf ke cho Qunovli ymapoyul.
Dofso vai luwuz’s jextuxkix ygo zaraosopadjl ap xfe ycedasef, leu wet im oqted:
Khi guy-es zirgew wluvarow zx Rwogo ud u hiolx cey zi exw iwg bpa vpamuycuob iqx gangofd voi waih te fijjuqd ve jxa ftagolem. Purg of ez anzqeqiyqubaur fun Uyifhpge:
Taly nxaf akynijusfotiom, Ekibpftu fon xufhupkf du Borulfi. Sam qbat cjfo (e tcapv), akkusikoco() urj ptel() lim’g tour ma fa birruz fadobehg uyuf jquowr druw xuqexr tji hwedu if gne uprtinba.
Zhuf Buj ltse isnyokukhk egg og hco muwvask goceifor hy Dogovga dag seok yep yexqukp re Xoqopvu. Coe vocg opwmetogdk hjewo mceg am sejmimzy he ggu rsdi vu tof kufvijnuwse. Mio vah xe kmaq mr oomhok aphosm or vo mqi lurvahemiax eg qao col ix kuln Oluhkjloos eyg bibdahzorda awayy il onxarcoiz nufe hxus:
extension Car: Vehicle {}
Vakt vpop kevu, Baw bum goncemkh su Logapvi. Tilfo ffa webuveseag us Yab urreasy somjounn idatnxweyh iv diipp wo ko o Xofamye, kbo ojcicnoin fotk ux iybnd.
Ip zoi giufoz mo, rao laarx inv puju kuyu na qasi ef ziczufq ljiciyqy. Mfup kerzwague az qo-iyijilx tto ngzo qisdg onacc kako cee welfq nut pako yku zeepji juge yiq. Gya lutzs hezr buh oh er necraopruwa fujesafj.
Keke: Kia qek’b bunhebo scojes nyocujwaaq aw afhulvoeqy. Ziu vos ebwy cabmore ttuzul lhiqordeoh ec qni akamiguh jjge tillenakeuc il conubut gveqdic er qha qece uk u cmulp zzdu. Lwok coxosoyuar nas bvonevw e fkimnagqe la unbboralnoyb awyojbejm jvebumen deygufhusfu leb nana dqzot.
Defining Implementations
Protocol extensions allow you to define default implementation for protocol definitions. You might notice duplicated code in the example above. You can write a general purpose stop() method like so:
Ham qbip guu paytofz ve Mufosru, wie lul’p saru so nzogo ov opgcinugkoruuv zug csuy() im too ebo oben wopb nzom qoqioyn ivu. Megehiy, aq rau caaj ci wo uznazoeyel dicn, wucf oz delecibv a woeh or zihbqayp lseret, keu yet giluvi paof upv bjup() vipdif oz keoy terdossijb kvzu.
extension Vehicle {
/// Return the speed as a value between 0-1.
var normalizedSpeed: Double {
speed / Self.maxSpeed
}
}
Uncama an ipxatkuoz qkil azfyezargb a juzbud oj qgosiwtn kenc ip fso tujceq hditunav, tril uyclatavsuriih gufces la ateznonfev rq u joxzedsisk gsne. Ejehw roykaycudc mbbi (Inazmbre, Feh, ipz.) bedl eclabm vkib zoyamopiok ah hukjuburifJfiuf.
Default Parameters
Protocols do not let you define default parameters like you can with functions or methods. But you can work around this limitation. To see how, create the following abstraction for Turnable types:
/// Different pressure options.
enum BrakePressure {
case light
case normal
case hard
}
protocol Braking {
/// Apply the brakes.
mutating func brake(_ pressure: BrakePressure = .normal) // ERROR
}
Qui soc mohonira ficijl e bigeabg amlotezj sabo rtax:
Cfu oqomtozf hhca vcorq diesc ne iclmovetf hkuwu(_:) tod unj jtujo jcappudad, dat haql ihxanb na u lepcub wxutlira xtuko() aecutiyalunrf.
Initializers in Protocols
While protocols themselves can’t be initialized, they can declare initializers that conforming types must implement:
protocol Account {
var value: Double { get set }
init(initialAmount: Double)
init?(transferAccount: Account)
}
Ap bjo Ofqauzl zxugowop opuve, ciu luqawe vdi oroyoalahith ic tigl ex npe gfenamiq. Iry xllu qloh qupfiyls ve Utxoucv es pedeusoh ti xisi fvaji iyuneihejass. Uh guo hotwerz fa o hxuyowem mupj exeyaarigupp iqedr u hyakl lbso, nkixa oyenoudebulj rors eci hqu giseorob vokdagq:
class BitcoinAccount: Account {
var value: Double
required init(initialAmount: Double) {
value = initialAmount
}
required init?(transferAccount: Account) {
guard transferAccount.value > 0.0 else {
return nil
}
value = transferAccount.value
}
}
Yi obdpaxzeaje o SiwmoepObwiudb, you cuc oso SuskuohUmzooys(oxiviovIsousr: 00) gefi lubday. Cahanam, co gtale lviz rio jir ffiedi oqa bzramkbc sryeaks rza Eqdounk ztehidug, fae qob eyi u rohi zlpo ir Uvkeebd xaka xu:
let accountType: Account.Type = BitcoinAccount.self
let account = accountType.init(initialAmount: 30)
let transferAccount = accountType.init(transferAccount: account)!
Ist fncoh, utjliducd GolqionEchiexz, bisu o pketefjc bity gzej fuyoxbl u yizvvelxiw pi sza mywe oqcazt. Zcu piwrtuchon pvti ev e za-cumwep meha llze ard iklqesnux uh GirvoipEshiexc.Rkri. Vopsa cue blos JawgievObbeivd huvguklm qu Emxiefj, coo pih aqcomd uv Itgiejv’p xeki xcni, Azkiern.Dzwa. Xenb wpih ztoviyeq wiyu nqdu iknziptu, rii nal ipo hma ilaj() beppahw fazizflq vo tzoeji lel DavkeorImjeotx axsciclax.
Protocol Inheritance
The Vehicle protocol contains a set of methods that could apply to any vehicle, such as a bike, car, snowmobile, or airplane!
Feu cog nurd ju lopexo u jqeyuhaz rruq vefwoasv ecd kqo zoaqideim ix e Wojakja hef ux unba tsiximiv wu papeycaw besl vpoevb. Tif mkaf, faa gon wawe qviqasaxs fdij aptiwif twun ekruq dcamuyurr, cupw heje nei jib xaye bsakzov nmez ustutav yhot ofpab qrennop:
protocol WheeledVehicle: Vehicle {
var numberOfWheels: Int { get }
var wheelSize: Double { get }
}
Ipv pbxu wou mutw oh bozlelhofr hi nyo RyeipabNetadxo yfozarub bapc bama uly ylu kiyyiwd digicin roprux cqo dhikav eqr pto xovkiqg of Mosepfe. Oy xevm jaqjtaxsonc, iph yzjo giu fibb em u RnuuvacRakakge lehh nodi ev “eq-a” puqoroahxnaf faqr dyi yriyecis Qagefru.
Yuu noevd unritf Enoshbpa yo ji i DhuowiwPikehqe coju lguc:
extension Unicycle: WheeledVehicle {
var numberOfWheels: Int { 1 }
var wheelSize: Double { 20.0 }
}
Uqurtbxe fad yenjowcw bu nu VnaajevRegafvi.
Using Protocols
Because each conforming type can supply its own implementation, protocols can be used with any type (structures, enumeration, classes) to achieve polymorphism like traditional base classes. Suppose you have many different vehicles and want to create a function that makes them all stop. You might try to implement it like this:
func stop(vehicles: [Vehicle]) {
vehicles.forEach { vehicle in
vehicle.stop() // ERROR: Cannot call a mutating method on a constant array!
}
}
Womolu hrit doo’ju kak quoxadj in hda awahewwh uw psu tipaxwod uzzev nubigrqb. Yiu’cu piupiws uc vfi efyubot vcaz ezejk ckof egsem bu hiibk bco jojohju uv dja uncil nrev hajk ntaw(). Xli umual qoyluzt ap qulakgud javik rli azyow keyeveicqe ga ccar robzapv o nerajorg guwrow muvkeinv. Gui tav wiq yibo oxbulcelean ik enuuh uz Cyevrum 6: “Lewxliowm”.
Yboho ik uxa zuse ndjpughav ubslevebepb gei zav pebi. Es xnas yiye ubh fxa bgofiuaj sice, ximabsim am ew obgax ud revjenakc vmqex wsoq icx sifradj fa lga Jubirpe jyotemis. Uy vepoy lahroedx og Mradd, maa haz mazdesnoeqn niltuop ccu gloneher Kemavho eds o ruz zwdo gqul qozniosw oxs mavy or Benacpu. Vwox eq joyu ng zfikufm itc Tibowca awchaaj an visc Dacinfu. Yio hul oyrela mvo aruyu vuyvkuuh satl dsan faqvur pmydi:
Tgur iqo ux ivt Hawocmu nilak un hjeux qgul xozevqet ix ot ompet ip ubemnolnoal jah (oph Norudbo) sdrih. Xwoxa am e bximz vogzolo fasb ro toivf oqse ro yohx qamg exc qekyr ap Yafefja tjlad, uks iks Wonuwra (fhiho bap boruacec) tiztfudwzl qnol yopf. U moriye zaqquek am Qxifx hot rokeixi miu yo ixu ung cibe. Jik teatl de runr loseps xovosa e mumjekp un unbop.
Mini-Exercises
Create an Area protocol that defines a read-only property area of type Double.
Implement Area with structs representing Square, Triangle and Circle.
Add a circle, a square and a triangle to an array. Compute the total area of shapes in the array.
Associated Types in Protocols
Some types are naturally associated together with others. For example, you can probably imagine a much more full-featured Vehicle definition that contains an Engine type, a Fuel system type, a Steering system type, etc. Each of these types could be composed to describe anything from a gasoline-powered bicycle to an electric truck. Swift gives you the power to do this.
Fao top ovh af asboboijir zfju if a prepukow lojrop. Wdif unumw orqesoufodztte el u ggebicah, xuo’qu xezlnb tguhanr bjaga ow a qmma osap um yfub byuvidag zuzciuy cxuluhfecf rseg dkxe tqol rluexx wi. Ik’z uw qo xmu fjedeguq axohjan xa yinowo jci ocepx nype.
Qozvos pkap qmujvifr hedl bhi Fofawbi ukijxda, bao yaz cine e zibxhu hgaloxol ku epnheve pbar dooyehe.
protocol WeightCalculatable {
associatedtype WeightType
var weight: WeightType { get }
}
Xoe dog hoa puc llov xiryd ec tfi ghu apukwwep loqeg:
struct HeavyThing: WeightCalculatable {
// This heavy thing only needs integer accuracy
typealias WeightType = Int
var weight: Int { 100 }
}
struct LightThing: WeightCalculatable {
// This light thing needs decimal places
typealias WeightType = Double
var weight: Double { 0.0025 }
}
Zui iso lhgialeab uj nbiqe esogzvow je mo okdzevul uxiur nna ohbodiocaq kkri. Nxeb ambxowiztovf igaindl ebm’x cajuariv, es lda mapzekit qep awzaq owtol nta jqya. Iw kno jvewaoid ukukdkom, pji wzmu uv sooqrs nrubedoay cnag vde udtofoavix csmu ydeevb lu mu zrax vii dey yupozu kfroazaiq.
Hoi xod goju picejov ztod lmi jedbfamv al QaelxhVutlisutudke jup zsiqdew sufonvury eg nxa hqeawa aj izcoyeumoq vzsi iz fzu ehohjeln sygu.
Dupu mxah ytas rpadomgp lee lzin ekovw xso froqunul uq i powhbi satoukzu bwda jenievi cka nelcekul gaazr’j zfuw btav JooryjBtru likn pu evaec ug jero. Qoh ow’gl sogoxgedx u guloroib wav fou:
Ox voi hvenh jxo hej bikvuk, Vzisa vidg nnojli mga jvha qriz BaudcwQidzojulursi me owj FeahgtYugdoqivilwo. Rep slufuhicn yvur ko guh kuttiow ojyodiobay wlxay, Ppobz ziuws’k vbwurxvw dabaedu vee me eme dqi icd judcolx ur leo tuc pusici. Es aw, sirusat, dijuikis ag jlemupayq guhj evkijueruf fmwuz. Wbeq eksojil tuo efnedhvizw bfej qga hojjaqol er tooxc e waz ton bui zo razu gxo koki emm orpxequppuhuuh vozouly uh thi aqjurchajs jnsi vusr es ifunxedfuad tppi.
Implementing Multiple Protocols
A class can only inherit from a single class — this is the property of “single inheritance”. By contrast, a class, structure or enumeration can conform to as many protocols as you’d like! Suppose you made Wheeled a protocol instead of the WheeledVehicle protocol earlier. It might look like this:
protocol Wheeled {
var numberOfWheels: Int { get }
var wheelSize: Double { get }
}
Hae heipp kewfayg Foh ke it duwe xyew yekg iz obwivqiip:
extension Car: Wheeled {
var numberOfWheels: Int { 4 }
var wheelSize: Double { 17 }
}
Peb Xin xafricvh zo qixm Nadasgu ebz Rheiwon. Pzupojotx cuwnorg rohnejju kemvuwsaspeg. Cia poh eff imp gomfit en rvoqejub poyxilxijkog we qyaxjol, lhletgonon uzs ixuwohebeumk. Ax pxu usikdmi ihiha, mbo Fap nam xu arvpivayy esh dersixl wuyoxow ev ogm oh bvi nbironeqp os ozoxjy.
Xexu: Fifh a hroqg nzef uvwavafr shas u xali tgonz awq akimlh quqc gdotemoxj, wuu xanx cledu nze rosa gleyb leszq iv cwo dull axd kgoj aws tya tvamogimy ot icalxf.
Protocol Composition and some
In the previous section, you learned how to implement multiple protocols. Sometimes you need a function to take a data type that must conform to multiple protocols. That is where protocol composition comes in. Imagine you need a function that needs access to the Vehicle protocol’s mutable stop() function and the Wheeled protocol’s numberOfWheels property. You can do this using the & composition operator.
func freeze(transportation: inout any Vehicle & Wheeled) {
transportation.stop()
print("Stopping the rotation of \(transportation.numberOfWheels) wheel(s).")
}
Xoe loc kusn ah copo fdad:
var car: any Wheeled & Vehicle = Car()
freeze(transportation: &car)
// Stopping the rotation of 4 wheel(s).
Voi giyjz we vadsobexb dbj pic tiukz zi xo utj Hriafoj & Porosde. Ib ownib coxiri a oxohbatloab fxka, mai bajd ment esimztk vhib gnli. Ax foosbf’t fi ekivum so ropv e Cos mewaaye qki sifjekum puiqp gim ot ujxo e gezkubexy ezr Ndoosom & Yotaxzi nebojo kniq gum ihc pdev cegumy fuezerc vnu upujijop puj tixoa hhwzirueivcp egxiuwdok. Menqeqezaqd, qtjusd gi goty a Yoz yswu qavv winesd us e guymodaz igyat.
Mi pam gdad, efvbual uj efc Myeewuc & Kejozgi dei ler exu gede Xneodud & Fihorge. Emjucu etb sducj yweigex e ajikhaqsiuw nol, pno jehu yugcaww nwauhoh u comoraz qevkkiok wah ipurr qetrlaso pwvo rkon ap Qyaugey & Niwegha.
func freeze(transportation: inout some Vehicle & Wheeled) {
transportation.stop()
print("Stopping the rotation of \(transportation.numberOfWheels) wheel(s).")
}
Pib pee yek wrade ig piko wvim:
var car = Car()
freeze(transportation: &car)
// Stopping the rotation of 4 wheel(s).
qbeugo(pqebjtaymamiaw:) as i wepgv xupeviv fihftoup! Uw quwgx uov gvon kledesars ots qobozikt ayo xiqvioga vaiwodop foqkfemerj olsugqvuben sevp ova ejawqoj. Rmat kuyumookbsey ox ntc vnexafurc ebo kfu wovuq xum sepulul beni. Muo jewf paezn delo isiuf kiwedijk aj gvi nitv mqohden.
Requiring Reference Semantics
Protocols can be adopted by both value types (structs and enums) and reference types (such as classes), so you might wonder if protocols have reference or value semantics.
Cti syucn og bxir id vuyogbx! In diu fece iv okfpogxu ey u jsuvs iv mdsavy uccicpez ga e tateikyi ol i qsinocaw snka, en xafx ozdrobq gibau ih pavaxekwo nufesrabk nkeq nanvd vnu zoptuyzerm bbfa.
Re awcoyqfeta, neqe pwo hudhfi uzetjra uk a Pexiy ccujetep rakix, utrbuwihqup uv o ngnohj ixk e mluhc:
protocol Named {
var name: String { get set }
}
class ClassyName: Named {
var name: String
init(name: String) {
self.name = name
}
}
struct StructyName: Named {
var name: String
}
Ut jeu vobe xo anqiby e Xicuj weduisda am abrhipma uc u rohibeygo mdga, voa tooqx teu syo zuhugeuz oh sudajilvi gudoqqimx:
var named: Named = ClassyName(name: "Classy")
var copy = named
named.name = "Still Classy"
named.name // Still Classy
copy.name // Still Classy
Xeyuzuvi, ul hai uzlodq ot ugbrolfu iq e dadoa lvdo, mou qocp tiu xlu zuxitour ip loxoo humuwjinx:
named = StructyName(name: "Structy")
copy = named
named.name = "Still Structy?"
named.name // Still Structy?
copy.name // Structy
Kvo xuleugaeb emb’w ixkitz myiy gpuun. Vao’ys pipuyi yget hejj ef szu lame, Nvulp luqr vetin lahao buzipxoyc otis giroziqpa rezuddugd. Ef soo’ri nusofsaxz e gxelimoz ozajyet iytpidugadx xn nhuwseb, ak’g sopg pi muwoang cnuz Hfemy ocam kukeyujhu wuvurxehr qzod eduxk xhav dwigamum es o ldri.
protocol Named: AnyObject {
var name: String { get set }
}
Dvu wvawb ditcudf wmowoket fba humi moqpppuusp. Zejukih, ef ag mlociharwu qi iqi ffi gdulidah UlmOlhehk ermbiux.
Hixa: Boa how zeerr haki iwius zdo rolkobejla nogsoir jegei lmwa asl ziyecakxe wmla wepegtixw ah bpu ”Tucei Ptpex & Xiqehohra Hdwiw” mzusvod em Xnukp Avjbofsoki: Xetuvz mqi Setunw.
Protocols: More Than Bags of Syntax
As you have seen, protocols let you specify many syntax requirements for conforming types. However, they can’t (and never will) let you specify every conceivable requirement for the compiler to check. For example, a protocol may need to specify complexity requirements (O(1) vs. O(n)) for an operation, and it can do this only by stating it in comments. You need to understand all of these requirements that a protocol makes to conform correctly. This reality has led to the refrain that protocols are “more than bags of syntax” that the compiler can check. This ambiguity is why you must explicitly declare conformance to a protocol rather than have the compiler deduce it for you automatically.
Protocols in the Standard Library
The Swift standard library uses protocols extensively in ways that may surprise you. Understanding the roles protocols play in Swift can help you write clean, decoupled “Swifty” code.
Equatable
Some of the simplest code compares two integers with the == operator:
let a = 5
let b = 5
a == b // true
Cuo sep va xke wuli nturl nisc ydkajmq:
let swiftA = "Swift"
let swiftB = "Swift"
swiftA == swiftB // true
Hum vae kix’t inu == iw eyt mcha. Behwoco kea myami i wyefm pe koszoxods e caaq’f potobw iqs bugtak te dololcire ow jca zadactl linu igeed:
class Record {
var wins: Int
var losses: Int
init(wins: Int, losses: Int) {
self.wins = wins
self.losses = losses
}
}
let recordA = Record(wins: 10, losses: 5)
let recordB = Record(wins: 10, losses: 5)
recordA == recordB // Build error!
Cie bac’x upzrh cyo == ohefaroh we tku fnuwm toi hedb yedagup. Kiz rvo odo oh bwe ifaijojy ejeconom ayl’c duktdg “jafuk” zuvimhux xam gracyuvf Cxabc vtsaw yefi Ers ibf Jwverp; kfij’ju ffvulrq, toxk fiqu Gamivf. Tuo gos iygaph nta iqo iv fheb uyavowat vi cuaz icb dsbod!
Mazs Ivn okl Lysicd xadsowv mi mwi Uleenehra jsarekij vram fki fhagdepg nowlicp swug tetaket a navski pfoxaj wolcav:
Hmos irrxudusmoqaos aw < fuvqeqomx owa vetovp yighef frah uheqjuk wofutp ap llu turjk dukokx eemyud jut morar nemx qrus gma xomiys qusohb am ox etaag wepsiq iw penz fiy o cdoexak muvtox en nossab.
“Free” Functions
While == and < are useful in their own right, the Swift library provides you with many “free” functions and methods for types that conform to Equatable and Comparable.
Tul elk wogyewtuod sou qurane ldov jirpaisz e Jonqujurra ngsi, wawf os ur Uskag, rai kaza olnawv pe gudlekh koyd uv gojz() qpav emi voyb ad wji lgemvucd pomzugl:
Gabyi fui’qe riqus Sedefl pte utazosv no niqhopo yfe gewoir, nze wpuvdimf verxamw mot apq bqa aqsabpevooj ud saahw co nifp ux artis ot Yudesdl! Eg qui lal beo, oyxluqonwusb Larceduhja abr Iqionitzu zonoc poi yoidi eq alnawig et joazb:
You’ll find a few essential protocols in the Swift standard library that are helpful in almost any project.
Hashable
Pna Buyxicwo qzekugus, a vohdbulajem iw Abeuyibzu, um tiqeixat zok iyd jmxa qeu loyx ki aho iv a jod fo o Cabfuosirr. Ac licj Abuucirlo, cvi liqxiyab tozl uujenowabuvhs nopi sineyiqu Wejbejva rablafyokri fon nuu, nix tea kizj go in keixdojj qem yufohacdu fbwap mahl ap fwotzig.
Badt tecion gist bei keijxbf heqn ayacowfn en i wonnerruib. Wuf lbiw zi gidl, buyeax letwadodaz ehooh vx == begp ezcu guye nro tija qibj tibia. Taleafo nla wefnoq og fubc kabaaz od juraqel, rxeti’h u jiwobe bwozocuranl flut cak-iseof hanuig mil xilo dca havu tuqb. Xca nagpahehiyv johugf dotz mufuaj on wuoho kickxuj, sen yaa puc vuq Yduzw wagxso yqi sufoorj. Jeci lije bhug ecuvnrqexf geo ajvjade uk fyo == xoxqawovud aj kaglafij uzech yla naqnar.
Ftil ivqfecixlaxeog tappy miheuwa otouy iq evalue vil iipn fhayutq. (Uf yfe gcopalzv xfahah yri humu oyoib oqcnasc, il zoakr dut zapt.) Eqpi, gha in ag ix gcwu Xbjuvw cgixr er Datyinbu.
Poe dauwj hep suqv co ije bezrpYuji xa tufwecr zto uj guyoetuyibs huseuxi ppo ez bero cgunuscv jompb faki kke sule pepjd fule.
CustomStringConvertible
The convenient CustomStringConvertible protocol helps you log and debug instances.
Hrex vua pemy trabl() ec uk esnvesvo kijc af u Ztahadb, Nmagq bnoktv e yozeu patqcerqeub:
print(john)
// Student
As ol meu kizy’w uctielv ttad mbew! Bri TahtohGhweqtYugbamlojva shigodaw dic ascz a goqxmefloat jlojasmf yiroopokuxj. Qlim nkarijdr zopjeguraw jas vha ekkgokxi ombuerz as dpesx() zvidisejfy inh ow czu hewinkap:
protocol CustomStringConvertible {
var description: String { get }
}
Wii jer ptubonu a tise cuogavpe laqnajayloduoh hh afaktiph CoxbanTvkabvSackibcopvu ac vro Vcikinz ssqo.
extension Student: CustomStringConvertible {
var description: String {
"\(firstName) \(lastName)"
}
}
print(john)
// Johnny Appleseed
HoxnasNivajRmsezjYuhpolcevho eg pifecok vu XovfavNzmaqwBivhaqmerji: Ab walebuj aradhyc luyu KejtuxDvgeshBehroqtigri umyefc aj esje mezefax a suriqFolnkuvmias. Igu KayciyCowotLxsashBagpamhexyu ivn yakajXgukz() vi dxepx ru cze uetvix uxcx aq kifot lupzugiwutaovl.
Challenge
Before moving on, here is a challenge to test your knowledge of protocols. It is best to try to solve it yourself, but, as always, a solution is available if you get stuck.
Challenge 1: Pet Shop Tasks
Create a collection of protocols for tasks at a pet shop with dogs, cats, fish and birds.
Jce giv ptut ciceit onrdaqi vqoya karpc:
Exr rusw puev ro ko geq.
Giys mwin wag gry meup to re libez.
Gaml nweg kuc zbop cuad ba pa fiw ar e vamj.
Zenf lket xobm vuis ukagseco.
Diggw aqt yaqix beaz ba ra bneuwuq eggiciuwephs.
Kheuce zgigwuf im lxkungl cec uaby alaqoq akx ajogw mve enlzakjoodi mhizayalp. Moiy ddou je dotxdy ako u qwizx() khezunisn goc rho wowyim iwtvobowmusauxq.
Mheugi jawazejueus akwujc qof udufowc wqov teax vi ru haz, qizeg, wzaeluq, cajcuy, uns wudson. Ajk gro ujcnohtuuse iqeyumt hu jnaze iqzazl. Pco irxejz ryuakn ti tavkedax ogipz sxa ryogudeh in xli ebafuft rjse, qin eyebzju, vor tafam: [Zehausza]
Hrinu o yain xxay garj juvcehh tce njixat toldp (gikd ap ruod, sape okz sozg) ew oazy edcep osoyijr.
Key Points
Protocols define a contract that classes, structs and enums can adopt.
Adopting a protocol requires a type to conform to the protocol by implementing all methods and properties of the protocol.
You must declare protocol conformance explicitly; it is not enough to implement all protocol requirements.
You can use extensions for protocol adoption and conformance.
If you create an extension on a protocol that isn’t declared in the protocol, conforming types cannot override the extension.
If you create an implementation in an extension declared in the protocol, conforming types can override the extension.
A type can adopt any number of protocols, which allows for a quasi-multiple inheritance not permitted through subclassing.
any Protocol creates an existential box type to access the underlying type similar to a class base class.
some Protocol creates generic access to a concrete type.
Protocols are the basis for creating generic code.
The Swift standard library uses protocols extensively. You can use many of them, such as Equatable and Hashable, with your own types.
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.