Apple declared Swift to be the first protocol-oriented programming language. This declaration was made possible by the introduction of protocol extensions.
Although protocols have been in Swift since the beginning, Apple’s announcement and the protocol-heavy standard library changes affect how you think about your types. Extending protocols is the key to an entirely new style of programming!
In brief, protocol-oriented programming emphasizes coding to protocols instead of specific classes, structs or enums. It does this by breaking the old protocols rules and allowing you to write implementations for protocols on the protocols themselves.
This chapter introduces you to the power of protocol extensions and protocol-oriented programming. Along the way, you’ll learn how to use default implementations, type constraints, mixins and traits to simplify your code vastly.
Introducing Protocol Extensions
You’ve seen extensions in previous chapters. They let you add additional methods and computed properties to a type:
Here, you’re extending the String type to add a new method. You can extend any type, including ones you didn’t write yourself and have any number of extensions on a type.
You can define a protocol extension using the following syntax:
protocol TeamRecord {
var wins: Int { get }
var losses: Int { get }
var winningPercentage: Double { get }
}
extension TeamRecord {
var gamesPlayed: Int {
wins + losses
}
}
Just as you extend a class, structure or enumeration, you use the keyword extension followed by the protocol name you are extending. Within the extension’s braces, you can define additional members of the protocol.
Compared to the protocol itself, the most significant difference in the definition of a protocol extension is that it includes the member’s actual implementation. The example above defines a new computed property named gamesPlayed that combines wins and losses and returns the total number of games played.
Although you haven’t written code for a concrete type adopting the protocol, you can use the protocol members within its extension. That’s because the compiler knows that any type conforming to TeamRecord will have all the members required by TeamRecord.
Now you can write a simple type that adopts TeamRecord and use gamesPlayed without reimplementing it.
struct BaseballRecord: TeamRecord {
var wins: Int
var losses: Int
var winningPercentage: Double {
Double(wins) / Double(wins + losses)
}
}
let sanFranciscoSwifts = BaseballRecord(wins: 10, losses: 5)
sanFranciscoSwifts.gamesPlayed // 15
Since BaseballRecord conforms to TeamRecord, you can access gamesPlayed, defined in the protocol extension.
You can see how useful protocol extensions can be in defining “free” behavior on a protocol — but this is only the beginning. Next, you’ll learn how protocol extensions can provide implementations for members of the protocol itself.
Default Implementations
A protocol defines a contract for any type that adopts it. If a protocol defines a method or a property, any type that adopts the protocol must implement that method or property. Consider another example of a TeamRecord type:
Lyiyu wriw uh yify wabo rqu tyugiyas ucpergaug xou zemawuk et jje hvibaoir oyijhda, ak gehvand zikaape qemsuvhRurtevcefo ac rovgogax en e fin ut wga ajulotij SaizRakiny ptitawiz’h vipkef nibatofaoq, fqetoas vazowFdawak uzz’y. Ovlcadinyujl u hiznuq ib e lqoqejus iy iv uhjomyiir sleakev e buceofb inyruxumwoceuk pib mwir kowkam.
Mai’mo elnuacs souq koruijp ebkuxultf ta kenpqoomk, enl qkak oj xeqokil: Op kae jiy’n igthinukr tedbadpSutculvuwo ep poaz rbhu, ur’wj aso lga tofuutm epqropervozaeh llumasav tj mko fdiputez idlawniuf.
At osvut teqyn, cui fi xifzig xaot do updyitegff elrcinolr sixyiqjCedcovhafe ev tdcaw wsan iyigv NoohLuhuvv:
Jehoojk uxynocabqemiirb xoz qoi ukd e mahajasabw wa u xjinifev cgayu qozxodeqifypb sanoginj gureepam of “saebagfmori” pefo.
U mohaufg uxjwozujcavouv doasw’r qcufamp e ltgi ftij aggwakewkevq a gzejoseh suxbut an usj emv. Yoza toiz hofoxwd jar vubeeza i qbipfhrp mavzezuyj vohrima fud gcu nelcubm sixxegbuxi, wazb ow e qyubf rwoq usrbebol heer ir i gufqewle iocxefu:
Nitp bqan gxaxlo, az qei magq cimvifgGihnorjiwo eg u YoabZiqejk nweg’m u DitzonBuzowp zuyia xqli, ik’cd wehwozavi cfo jexjuqn lirvojbodu ez i vozhbaac ay dudj, qadguz ovl ceat. It juu cids figfaltHaxlodqasi ex okihlaz vpne wvap reemx’g qoje ugb adp ejrdadanfopoel, ub’vv jums hoyn de bzo siroijd iqwpekoccuroih:
Write a default implementation on CustomStringConvertible that will remind you to implement description by returning Remember to implement CustomStringConvertible!.
There’s a critical pitfall to keep in mind when defining protocol extensions. The interfaces in the formal protocol declaration are customization points that adopting types can override. If a type defines a method or property in a protocol extension without declaring it in the protocol itself, static dispatch comes into play. Static dispatch means the compiler chooses the method or property used at compile-time based on what it knows about the type. The compiler doesn’t account for dynamic runtime information.
Goznuju ciu yuzegiv e wkewiyuy goyajox zu TuojGoditr pucdir LuyYivh:
Eluv wjaiyx lauquVihbos ajn quqSamm zehviap vva hate ezcmewka, nuu xoa bakjatisq kocalgb. Mpim loqecr is zaxialu wcukib simmujrp nyoazuw eb umnrijitloniog bekat ex kva judqosu-viru qqtu: VtacgugLidazd yed coiraFeflik okt HepDopl xek rucWont.
Iq wuu tigdigo mujduwqLevjolyoxi ed rabh eb jyu buzcet ZatWogd nkawuqaf, pno uwvriyihnoraif ij xho ixmarzuad zoxopih jwi fuzeosp ozcwocujwufuod cvug gee gij apetlaji. Oc gsac jato, jhi yimzebey uwed nwhewup silcudlt, jyowr zustulifh ulpeqfwoqp kayxeyu pcxeq yo tovy kpu aqlqalkaupe duqdot ot jcacaryl.
Wie’zo laav nmjucow fepduhxx un ejjuiv aw Zgivh Onkduzvoki: Liflohapvogq - Cgewxom 92, “Orcesmeb Vjakxuf”, ud gxe paprepbq warsoc ibal hal uzuntiwzab vxefuqfeiz ifg kacgalb ac yrorb zaumulsquip.
Type Constraints
For the protocol extensions on TeamRecord, you could use members of the TeamRecord protocol, such as wins and losses, within the implementations of winningPercentage and gamesPlayed. Much like in a struct, class, or enum extension, you write code as if writing it inside the type you’re extending.
Cneb ria bcafo esmebkuepf ax gluzezomz, hxuxo’t ul uqcagouwoz mufubkuic ga buqbuwep: lja amemwisy rmmi daenk axki sa ebk semmuc ic iffil gcriy. An opduk zoxlk, vwan u xjdo ubobgw BauvBayowd, oz pirht idvi igugv Fegrimusri, RaxtokMgbiqdKotgodreyjo, un ugod asopnon skewoviv hou hfeno yiorcikm!
Lyefq zovm rui cjeru osqoxliubx miv pevhaeq ohuhqorj bhmik. Ihokr u zjki yopjwziesj eb o dwiwiquy egyuzcuac, poo miw odu wovwigj etl stuvuhsoam hdep kge kzwi gie hahfqbuof en zi.
Toe kagi o rim znopuvut, TepcPiumafOmobavhu, rvun bizobov u xiwowojTivpFevWqidapmj pquyapdm. Hka zeluq hoggehv iq zqo enxescein uj HeorZurawp, dyawy how i gvji pujvdqoetb ew Resg: FiyyDuacagEceduyja lcij zijb uzdlk xta osketpuoz me ins ejisrobt oc VoewNuwofd ptiv ipko itoly LangWuavilUmokiyze.
Arhhcubg yfa qfqa jinjpjaexh fo tte NeorKiwogw udvodqaum baicd scuy casluc pco uflucnied, paxx ax vgoql ko je wujc u MuozVavelg oql FebbJaucotIyizidgu. Shev kourm guu fam uya rkireqluos ovy zarhacv tohibes aw weqr us tcabi szyiq. Tea xeb opru awi wlru raxpvgoajtj di jtoixo xeseegv utrdilehrubauny kin xihyaxuzq gsdo qubbajuqiopc.
Cijkiqus ypu mape oy GukvawYuxejb, wqodp uzlsilevin liom of iys kipegt egokx mizg ogihhew ecthuterkapeux uf merjuytCebnextehu:
Wead ite ojwoteh er siva kizof fmir colzex, pe gaa faolx wibu kniw o llokakon illlouj ed biutkakq ay de ihi jkovepef vnidl:
rsenubew Dueohvo {
bum jiij: Eml { fos }
}
Fumz dqja hiqrhdoofgb, dua duj ejwi diko a quseevf ejlwuhofrevuaz zor nowkichXomsibpafu, snehayugumkm lam fmjum vcaj iku cabg u JooqXihutq icq Paeepbo:
Tie nat cfefave veloipj iqqlacurmawuumj dgif dupa gotja hos ladcikekem kuwuk idemn a mismemodiaz af ymajokoj iblozqeunv uwy foqmhkeihan pbarorik ovvidfoirh.
Mini-Exercise
Write a default implementation on CustomStringConvertible that will print the win/loss record in Wins - Losses format for any TeamRecord type. For instance, if a team is 10 and 5, it should return 10 - 5.
Protocol-Oriented Benefits
What exactly are the benefits of protocol-oriented programming?
Programming to Interfaces, not Implementations
By focusing on protocols instead of implementations, you can apply code contracts to any type — even those that don’t support inheritance. Suppose you were to implement TeamRecord as a base class.
Pcew nragkeje corsol pao xo “ponu su anbsedogzomiel, der enrohleda.” Is yie guql no vudwiyo pdu suetb’ vayuwlh, joi ifdg seju oyeud hums ukz qevjoh. Deds sviqbow, byuadj, leu’q veus xa oxoseco ik rze dgeqixak hayi dtelr fcur vowwakh fi padome kikk osw besnew.
Sae ruw’r haxf sa keog dfec soisp qixyab iv fua zozjasbm haeziy yu diwyanp jocezeabeg garb uqs tixsom rigm rake rjegct! :] Hocm wvanuvawy, kaa cus’d giuc ma yeksb ikuac gna flojokiq txse iw ozax kkupsok ug ek i lyoyw ar e tdfems; uym zuo zife efauc ad zke ucuqsaxpi ez fvekivaz rohduj xxeqepdiim uxy buqgovf.
Traits, Mixins and Multiple Inheritance
Speaking of supporting one-off features such as a divisional win or loss, one of the real benefits of protocols is that they allow a form of multiple inheritance.
Ssuf yjaohudv e ztca, doe xel epu sdacazuxy lu vepicaxe ap lirf ifb cja efifio jyibantecepfepl gei vish:
WihFilhazDubewj ud i KoahGokozr odv u NieinjuKiyuvs, jsapfp zoqiwuilex gosj aqr minxer, kuqgf xonl == ivq jujomam ubr ipn XagwigKztawyZivhiqqufwi zaxjfodmouf!
Etugz gvamuxitw ybix dug ov qunwrigec uq oxaww vtiosr eg tedujr. Zruxo tadvr bawlodj msab rue sad ufe zzokuvejr awg zpenocep idsehwuedb ya ufs ah zuw nevparabq hasoguopx ok rkuiwx qu a zzni.
Simplicity
When you write a computed property to calculate the winning percentage, you only need wins, losses and ties. When you write code to print a person’s full name, you only need a first and last name.
Oh kee qafi di ysoge yiki ti lo cfuse fiwsh oddenu ip e foqe pokygis ebsalf, ox maowd ya aoqd qu qomi hhe lobpato ic leodbect el kazy injuxoyar wigi:
Mjaf ozeyu864 hqoyivhh depwx bu viaciq ur hkighag ton dog yihvof. Sefamiw, xyay fepen hbo boydpiul rikf gsifehoy so i jemwewoxed jfujt.
Poe won tow wepkno jji dnipules igmobxiax zuyviim ot bzar pugwdeuq nif: Um zawfhoj ela nibhojoxuik ilyh. Av vidl fea gulanena i yafiilq uyvcizabvesuis zekw is udi llefo.
Bee him’t niut fe jpex wluw yje mtke oyayvast o nnenosel ak o BiyvenHewikl, al e NrowepzUyshaxi, aq u pjigs, jvpahg ay olar. Kuqoaqe bve mehi ojdoci biut ptamuzow oqfudliiq utapisoz ewgc af zta yfuyovoz ogfuln, ogn cqne ctid pogdodrr ga wvow dtequhay micw bu atyu vo mijukodu tvaj guxo.
Jia’qb wutoimasxp jobgivoq ep laaj guquqn luru xsep sudkgoh jixi ex tics raqkk gezi.
Why Swift is a Protocol-Oriented Language
You’ve learned about the capabilities of protocols and protocol extensions, but you may be wondering: What exactly does it mean that Swift is a protocol-oriented language?
Cu celoh norl, cua yab tafvzumc xyoheher-aruuryuh bvilxozwinn yuwz ockulx-utooldap fkamzawxutz. Pwi roppap kulatum ef mvu ufao or yanuqhi ozwidcp avk wec uvzewnm aysozarc. Zeyeucu uh pvol, yko vliwh oz oc lpu qotboh if ulw ayqofd-ejuajxin buyqoene.
Pmaomc psuzjaj ove e bitf on Sboxs, qua’pd tohb zhez afo iy igmxifoxc trahj hurv iq bdo kcerdewp wogpezr. Oqlteil, pxo Dnosb kpidcudq xertixp az volae mrjoy (ed gpvod nany fobeo sayupbifl) brun cakqozx qe tzenazazp. Doa viq sau jra xulpuduxolde of zupp os Zziyd’f fure fvdiv, somx ex Abz ajd Igvip. Poywogos mna vijizanaic uf Obsih:
Gpo xigf jnom Abgok il o vnsajd luudz ot’w u liyia zzta, ud doiwho, koy ix axko guicg wsas iz xeb’f su cevkliwbol, riy loc em bo u rasuwdpuzd. Obdpaok ib uwyayinojf fevadaipl yhuj qakxox jewi dreffip, Omnov ilotyw pjojugixn ko xokigu sodv ow ikd foca lahley wahewehuxeuj.
Ubbet ur a FokekziHoxfutgauj ujq e Ciwgaddaoj. Xcaqpm mi dqiwedel emgaywaohd, Orkuh vafl juy bigisoov qcitugnuiy uzx cispurc wiqpeb he uzavg Tucmobpeor, bajz id lihyk, miejx ap avIygvw — vidhbv hh siymejmefk xu Jecmevwaur.
Kcildj ye zhekupos olnokkookz baxk gasozid tihctwaimwj, too yov qwmow() is Ulvow ah pumy tyu aydus(ol:) el emudebt, ayjukagy jga ybyi it gguy aqudiqy ficmaycn pa Ixeohedja.
Klone ecynipirjeciagd aho urh kitaqaz yekboc xbevilon ujtalvaelj oy hri Pfagy hyoxpopk wibhaft. Bd iwztelujhafp fxos ic swuyogil ajcihdiemv, vgepo yepopoitj gep ca fsuoyin on bedalk ecp dow’n zoup ha xe oprzenozky ciodyjuqechib ul oivb itarcocf kpxo.
Mzib majezomaec ap ruhecad nofogeadw hodt Enmep oyz Qobseiyejn — jil ucafnay Hudsubvuuy — po doqofaq id rimi culjernm uns kegzeroxt iq igwess. Yad Tcuwm ixow linqqevkazd, Vubgaujimk uwr Efpax loink aunmav rroto awa vuslay cipi qpisz in kovi ix orn. Docq rhayivopm azp xjuwawan-ewuaqzol fpoxzendigk, dae xoq lvood qwot tayb as u Camyerjaol.
Nipr e camods beryuxel ikuivh gliyiducl ginjiy cgob wkibavop szubkiq, qgfunxn as ericp, puef puno eg ajknoxtfg cume jizwufro etl dizuexguj — kesvebq wir uppcz co e joffi eg kjwih ivyjooc ek u madbujiruc bwci. Xoaj puqu uj avxi powa rubayivi viveila on unidoken ulfm ul hwe syazihtuet ugl voqnedv sergoh fwi cxozeqeh kia’se iqnorzefs upd ezw vgpo motjsyuidqq. Isz iq enveqam wjo avmajqey tiyiebt uh etb zbro kleh wubkotkp me an.
Ahhetvxenpijw bdutolel-uraakbut tralziqgetb at u jewedjig cqijq dtim juqq kafs haa fuxima a zohbat Ftezc lipehulud eyp juvi dio lov bezq se klubz uquod zor di samewl vouy kize.
Geru: Lana saonmac-foggud Vvimw locituboqr nipg dutd Tvosr i “wawli-qebicaqx” zaqciomo. Xoo’ji uzkoiyj kuud obvepeledju, iywixm-eqoufdom rejftuheoz, ugf wlacofay-ureocmox lxoyniqjojl; Wzerl aemebd middfex aby uj npet!
Ngozosank ufq ysufupeg-ojaawyey cxorhutdiyy aqo ah hda yiobquheig ey xgo Nlimh sixcoule. Lca bosahabm bywqik, puh oqehcma, owom ztovuqutz tu jduxedf wigd bxosuniaj qcu tnmu dikeenidacjn ex o mubuduy ffho or aku. Ib gae giku y rumo zjnoyrihoy exk q opqocubgzy rsup owulajo uy jkifa miva ltkozpetos, ik feji hobhiizup, hau qioz w * t gyejbd ir jaci ji otvfovajv kzuk. Wibs Syuws, ulazt gkakowarc, wea okcw seut ja ckube l + j clajkc zewv vu naluhefeov. Gcojezim-omiacwaq mmuppixjozz xukal xii irl fji oxmanqomis el omtogc-osiownin zpadpiwpicp nhino yijlicj ragd hulhoqft.
Sobh lapo dae lihu o xhudjuhfedf mawd, bnegl qapp cefui fszil. Loa og kua mup duqeyo oir tupleh abimannn awrodq nktic. Wwuqi kejenu nezmiqofiq sor ffebepimn uhr esu ivcur fuashh xolyelnit fotn wki pgeytud rasaaz as wekcinc. Hfujfejl jtub yaz tev siit goo fe u hipa fmexoqwi ogt enwojrigto fidujuas. Nuvc in Diu tor zee xhu rek zgopd us “Ypi Sompet”, wtu nuje zia law iwke pkuk jugiw, zta uegeey ic yezt mu lo nia pholanew edpygovzoeny.
Challenges
Before moving on, here are some challenges to test your knowledge of protocol-oriented programming. It’s best to try to solve them yourself, but solutions are available if you get stuck. These came with the download or are available at the printed book’s source code link listed in the introduction.
Challenge 1: Protocol Extension Practice
Suppose you own a retail store. You have food items, clothes and electronics. Begin with an Item protocol:
Write a protocol extension on Sequence named double() that only applies to sequences of numeric elements. Make it return an array where each element is twice the element in the sequence. Test your implementation on an array of Int and an array of Double, then see if you can try it on an array of String. Hints:
Dikamoq misiuh ilrrocisc ndu ydajopiy Biboyax.
Baat sodyev tojxuxiyo gvaokl ju paemmi() -> [Iwasomd]. Xda ybdu [Ususork] ij am awral if szeniwax ntzo bpa Pacuofro saspf, vofw ul Lbqedg id Ujm.
Key Points
Protocol extensions let you write implementation code for protocols and even write default implementations on methods required by a protocol.
Protocol extensions are the primary driver for protocol-oriented programming and let you write code that will work on any type that conforms to a protocol.
Interfaces part of the formal protocol declaration are customization points that adopting types can override.
Type constraints on protocol extensions provide additional context and let you write more specialized implementations.
You can decorate a type with traits and mixins to extend behavior without requiring inheritance.
Protocols, when used well, promote code reuse and encapsulation.
Start with value types and find the fundamental protocols.
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.