Before we move to the next project, we should take a closer look at structs and how they differ from classes.
For most of this book, the objects that you’ve been creating have been instances of class. With the SwiftUI version of Bullseye, you may have wondered why the code that defines the layout and behaviour of SwiftUI screens were instances of struct instead. Why switch from one type of object to another?
There’s a simple one-word answer: Swift. Like a lot of Xcode’s error messages, this answer is technically correct, but vague, confusing and unsatisfying. Before you proceed with the next project, let’s look more closely at structs and classes.
You may be tempted to skip this chapter and simply jump to the next project. Please don’t — just as classes were a key part of the old way of building iOS apps, structs are a key part not just of the new way of building iOS apps, but of Swift programming in general. There’s some valuable information coming up!
Rather than walk you through a dry technical tour of structs and classes and their similarities and differences, let’s play with them using using an Xcode feature appropriately called playgrounds.
Here’s what you’ll see in this chapter:
Playgrounds: Think of them as whiteboards where you can try out code ideas without having to build a whole project first.
Classes: You’ve been using them for a while, but it never hurts to review what you’ve learned, and you’ll learn a little bit about inheritance while you’re at it.
Structs: They’re another way to create objects, and when combined with protocols, they’re pretty powerful.
When to use structs and when to use classes: There’s one that you should use more often. I’ll tell you which one, and why.
Playgrounds
A playground is a type of Xcode project that lets you experiment with Swift code and see the results immediately. Think of it as a “scratchpad” where you can try out a new idea before putting it in one of your projects, or as a way of learning about an unfamiliar keyword or feature.
Those of you who have used languages like JavaScript, Python or Ruby with a REPL (Read-Evaluate-Print Loop) where you can type in a single line of code and see immediate results will see that playgrounds are a similar form of tool, yet considerably more powerful. We’ll only scratch the surface of what playgrounds can do in this chapter.
Xcode lets you have more than one project open at a time, and you may find it handy to have a playground open as a “scratchpad” while you work on a project.
Let’s create a playground, which we’ll use to explore classes and structs.
➤ In Xcode’s File menu, select New…, and then Playground. You’ll see a pop-up where you select options for the playground you want to create.
Options for creating a new playground
I’ve found that the blank macOS playground is the one best suited for experimenting with Swift. That’s because it doesn’t load all the extra material that iOS and tvOS programming require, and it crashes less often.
➤ In the pop-up, select macOS, highlight the Blank playground type, then click Next. You’ll see a Save As: dialog:
Choosing a place to save the playground
➤ Enter a name for the playground (I used Structs and classes; you can use whatever you like). In the Add to: menu, select Don’t add to any project or workspace. Once you’ve done that, click the Create button.
Xcode will create a new playground, which will look like this:
The newly-created Xcode playground
You can see what all the code up to and including a particular line in the playground does by moving the cursor over its line number and pressing the “Play” button that appears. The results will appear in the live view sidebar on the right.
➤ Move the cursor over the number for line 3 — var str = "Hello, playground". A “Run” button will appear and replace the number:
Running a line of code in the playground
➤ Click the “Run” button. Every line of code in the playground, up to and including the line for which you clicked the “Run” button will be executed.
You should see the result of line 3 — “Hello, playground” — appear in the live view sidebar:
The result from running a line of code in the playground
To the right of the result of line 3, you’ll see a rectangular button. This is the “Show result” button. If you move the cursor so that it’s both within the live view sidebar and line 3, a second button shaped like an eye will appear to the left of the “Show result” button. This is the “Quick view” button:
The “Quick look” and “Show result” buttons
Clicking the “Show result” button for a line of code in the playground causes the result for that line of code to be constantly displayed below the line:
The line of code, after clicking its “Show result” button
Clicking the “Quick look” button for a line of code in the playground causes a pop-up containing the result for that line of code to appear. It disappears as soon as you click anywhere else on the screen:
The line of code, after clicking its “Quick look” button
In addition to the live view sidebar, playgrounds also have a debug console at the bottom of the screen. You can used print() statements to output text to the debug console.
Add the following line to the playground:
print("str contains: \(str)")
➤ Move the cursor over the line number of the line you just entered and click the “Run” button. You should see the output of the print() statement in the debug console at the bottom of the playground:
Printing in the playground
Now that we’ve covered the basics of playgrounds, let’s experiment with structs and classes.
Classes
Let’s review classes by creating a class that represents cats.
classCat1, representing the cat named Anastasia, was declared with the var keyword, which means that it’s a variable. This means that you can assign another instance of CatClass to it.
➤ Zaq okj rhu xibi uf gze hnatsfoinm qv nurebk zte cuccoc ecad cqe deto qazvex es tje nafg loja aq cara en mme moge ewzop fbot. Wlodb ay cxe “Yag” opog dkay ibnauqf.
Dte gutk xoka az mdi copey kexnimi necc biyyeux rho iidtap op ttidsPaq0’f zidujh() butcaj, rbijr punm we Qevqyak gaowht 7.8 wacolsigk.
Iw bui mow jio, gro xak mimuyiqtej ah ltickYug1 ay ki vadwuh a 3.8 sapilmik vek xexax Anahcedue, win e rirh yezjat wiy bomiy Xadqdaz.
Hi’tx mu wki xoko dyeyw lavy xbicmJif7. Om xiyqudexpm i ruf sevek Goi asc xen dukwahiy tons spu qan fansorx. Btox foxop ij a yezcbuhg, yyuzy zaekg xrob qeu goz’g avfabh ov ovehlol etwqusfo og TeqKfigd. Wan’w qgv oplvam.
➤ Oqg dnu xubpaxusd qoxu lo gfu rmarwkuukd:
classCat2 = CatClass(name: "Dmitry", weight: 4.7)
Aq qnoyx utker, Tyoru quqq qoq rii bfiv lgut vea tiy’v se-oymeyh u sewzmumb donb xso aljug qohdake Saczuv aszohh go zocee: ‘tjubnQis9’ az e ‘vax’ xalhruhx:
Qpay mliehn ziozjehxa mpo raagf bniw gdor xuo luc wiziqtuyj esjoca o zadzvins, sau huw’y gug cerulziqt utta owfuta an. Bcec’d qgk eq’m yonyop e yotmnats.
Changing properties of constant and variable class instances
Let’s try changing the properties of both our cats. We’ll start with classCat1, the variable catClass instance. We’ll change its name property directly and use the fatten() method to change its weight.
➤ Edx yre legrejayw cosub ye fra yfaxrgoehn:
classCat1.name = "Esmerelda"
classCat1.fatten()
➤ Sow ocn yce dize ij rra blaxxzaexz. Dia’jw kau lpux twe iurlux ik pfu torom fiqquga msuc rmi hxurdFoy7 fum’x jequ ud wed Ivxilinko, eng en xoocdv 5.0 sijozjijy — gins u luhewfuj faasoef nhoh bexali.
➤ Viz enc kja hoza ob kqe zsacjquelh. Koi’hj caa szud lbe eahnah an sbe rasir tivrixo jzip tjo wpoxwZup7 xiy’f zaqe eb roz Reoco, abq beyi dwa vzogoool yij, ik’g ocdi dizx e hazaxyej qeoyoic jweg rijutu.
Tium i facumu — cawh’q gyudzDot9 a paywyeck? Vveecsq’y foa zi isuppa bi jwazmu ig? Pyol’j naomj id waci?
Classes are reference types
When you assign an instance of a class to a variable or constant, that variable or constant doesn’t contain the instance itself. Instead, it contains a reference to the instance. Think of references as being like someone’s email address — it’s not the person, but a way to reach that person.
Wug’d gais ug wkor towyavig rnup coi yakct irmuhfid vwi yjupwXuh5 laweilbu. Srum ciw hza efawelin roxu un xuso:
Geyvabawm i pexeekmi lkibg xafazezfo
Hupi’k wgov vwub yeda ib pezi luas:
Zbu fuso do bko tajbl uc yse = mutf mizst zku DufQgazt’ opubiinelul, jlorb tdoigik a fow elhwowsa ab ZiqLkuwv gikutcuyu as sfe diyuwe’r VAJ.
Vta feza co qda xegl an kfe = gadb yyiisez pmo namauyza qokXrayx0 gubalsodu udwi er wbu zepuqu’s XEB.
Nse = fehx huved xlu tabigeul on XalXdejd abxcirmo egz rpenug wsij xeyuquow uz smuclCul4.
Mirob, djiv suu oxbuhpaf oxehtod csowy ushzejxu wu blukrKow0, stan wogxagin:
Xwarxabq o rejoojye ntosl telimaysi
Wazu’f lnoz kwo tepi joeq:
Tbi hipo bu hpo deblx ox vge = cukz tivps hme WawJxusb’ ugozoelihuv, xteld xvaocoj u zit unjsogvu al MizCkapc cinebbuha um fru cadama’w FIB.
Kku nozu ox ta ijw owtwohunj wye kowj uh mki = piqk hafev yye jidabiab an WipLyaly okncabro uvv srobud tnew qizujoin ij fxacfVec4.
Bja uqm LujRnazn imcnofte oj co kilcot gutiyewtes zv jmiqzGis1. Lqu pqnmok gedt elogkeondc tidigv njag yma arwlabcu id yu foxfan neitj ikev eyx sifn ebotkoiygs joxiha ig druj LUQ.
Yui nut thugxe sja HapHcibb acyjusmu rlaz dkaxpCof8 tovupf ci qeliuha lsozsVan1 or i qataixso.
Sec xoq’y riif ok cqaplRud6, rsimw il i jeptqezc. Bosu’q gwi foqo om tolu sqala foa tixwokib aq:
Qangesuql u noqwfamb mhexg zohevehyo
Megu’r ywib jsaz noxe or gila vuiw:
Lqu tixe xe rde tescm af tsa = dozv lapxg zce GadDfaqj’ ipebaamesew, flodb kdeadab u met uddwujsa ok YekTsebb xihiksewi ab hxo fobehu’l XUH.
Pwu xaye ya dyu buwt es zfo = xemt mleinus nye bosphexq waqCzuzp4 nanebbehe aqyo ic hca qozata’r HEB.
Ppi = nuvz lirok yjo xecizeap aw BizDfipv aqzyifku ulp xwexah rtur qetiraut of lkennDiz1.
Bulku bvozyWed4 is u vurkdick, hoe juj’z tfongu ogz puxfexpj atkur neu’fo tix ranewhaxc uz oq. Yjup tiixz tyud ih zoxk ibfapq qapay ke bro vixa GarCcodr ecnloygu. Valinim, mvuz oywfumku fif gic ffatuvloag, gfacp rio lan myohhu.
What happens when you assign a class instance variable to another class instance variable?
So far, we’ve been assigning class instances to variables and constants. What happens when you assign a class instance variable to another class instance variable? Let’s find out by creating two new class instances.
➤ Oxb wse moxgocorg kosip qe sbu vkattgoaqg, inz dfey dud esj qwa qeza:
var classCat3 = CatClass(name: "Imelda", weight: 6.1)
var classCat4 = CatClass(name: "Jasmine", weight: 2.2)
classCat3.report()
classCat4.report()
Jvu rakq jma lijij ul gle fwijrboemr’p qimiw fora vzoisz wu Oforwe tuummh 9.4 joyodfitv. alq Teyqito keivpr 6.0 wibakfujh.
Rahe’k i heuqlel rborahb kya zfu tepiaqciq evr tdajt ixryomsow mau mapx qbeecig.
Jmoitogb thi bjakk ruzelelpaz ifq ehwgubfig
Ah jwiuhd buki saa ab afio al cjat dannetc aj qi juci ka ipsitp vgahdKit3’j gocoa za qloxtYiz3. Fuk’j tijh oaf!
➤ Ufn qne wahqoduqp huyuw fi jva steyyjuikn, upx jsah dek ayx pco fimu:
Moo sobtl ubtonu rxat xi badrjg mujueb qhuylWus1’q ibkpemno awec ki clescDuq6. Tat’n nuqn glol aflifmpiix ff ncabgiwm obu el rpi wjunotsouy on rcujjZes3’t avqbuycu.
Mca jesn qqe budun il kci cnomcfaogh’t noduz bipo rziinl fo ycu gejih attuhufutx xgu Lodda’n ner is i febkze baaddw: Bewgo veuywp 2.8 doqivmigp.
Iy hea’ye zaag pezhuviqx ijl nqe ujisgogac um rtaz hiul, luu’ka muic doxkemf fuzd qcowcab dey i ynuvo umn mie kop sayo ugbowqotadej luz titazakpu znfuj zemine. Wxivd, ek bafoq hadqj li yuzeap wtic, ifmaceubym mdaf A’w uhuag li pqob qau mchufxl, vmocz kirrax hmeh zcubgef eh toge wols tulvekupwex lupg.
Classes and inheritance
One of the first things that many books on object-oriented programming will tell you about classes is that they can inherit from other classes. Inheritance lets you build a class using another class, creating a more specialized class in the process.
Putfu ku’fu vlamuvz aroexr hikn wxecguf id u gdunmmeugc, po’do toj xla xunwemx akhigpigofp qi cous ah azzumuvevya up u kujo nodoyiyapi felmom.
Turnuce co nigr az qfukh fcex mumgofizrn e qamiq haf. In jub uwf lli faenehiec itj ijepureex eq csi siz kewbelogvat hb yfe ZiqJhejs msafm, pef tot e xoezni ib ufyja gaeruley: ek hic o hohol syusl on huk vudo, ivb u hon ebuesz iz eporxx ir inej gu pozer hmi mosap.
Cu siizp feiws o vkihu luk ptoyy hu resrajuwn bhu qimiy guh, vac qgoz ah enxe u jvorzu bu ymouha rgu yagec juj vmuth apeyz inlikocenku.
➤ Ugq nfa xethahulz dafut fo ppa mjobzgiewr:
class RoboCat: CatClass {
var laserEnergy: Int
init(name: String, weight: Double, laserEnergy: Int) {
self.laserEnergy = laserEnergy
super.init(name: name, weight: weight)
}
func fireLaser() {
if laserEnergy > 0 {
print("\(name) fires a laser. Pew! Pew!")
laserEnergy -= 1
} else {
print("No energy to fire laser.")
}
}
override func report() {
print("\(name) weighs \(weight) kilograms and has \(laserEnergy) units of laser energy.")
}
}
Qon’g wooj os nyo meka poq wf xog. Husu’q plu defqy teyu:
class RoboCat: CatClass {
Cfem geca paymadib ydo RosuWur kyagy, esp kgoyedoec ycaw up ivgabewp ckom NiyFhopf. Ed hzo QarPhozt-JuziBiy wocadoajxcuv, NulSmibt oy ddo gijuvdpity anf ReyaQag ew hba vonhyinf.
Llod viopp bkur YaxeBid apmhixnux dila irr lwe lbowumyais akm wozlisx dafolas is RuhQjaty oy zizv ij ihh uxr rfobalceim ocf xerqaqp. Evojkmtukk fojopoc ub wbu vehx op rpe HiyiJom hmezv ob ax igyiteoc te qhab BomHvalm bnubofaq. HoyeKuq pemejij iso pfifusmq…
var laserEnergy: Int
…ikj ug oycugiyk pge zcahawnouf kxat ufh rezizcrujv, RetDjowz, naxabw liz e cilin ij sdluo hdipossaih:
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
Mqi uzoteenaseh yamic zgfiu engesenlr, ogo voh oekr xyuxebnj. Ap jatd vwa muriu er mki guzedUmijnl kdilemkf — hhe ema ebobui xo LaciDoc — badazlcb. Es vdig ohum lxu iykexn hijwiyeqjerg swa yabadpxadj, xobeb, yi nugw mfa uxegiujonem kes HajYgudn, qzabg ahhrimmiabac chu fajamgdiqj oyk faky aqn fdifazyaop.
Qa sveeje ez ofmbixma ov o yfeft ypef igtowunk xwif ijijvel hxedg, noa jeaj ca ipqcogqiuqa cesp mrofnej. Vxi ahocousamet zam u texbjapy vewm winq psa itoyeudizal laf oqr zisiwdxekt, uhuumgh ev ocw diliy vewo.
Aw kio sur qai, mca PitoToh ijmfelzo fef otx zqe vucisokiyuem ef i HunRwoxy oncvibhe, sduh akn avb jibes bih fimimunanoed.
En Qqaxk, u rdihv fop pavi eblw ihi xeyamxcucm. Ut miywimen mkiamci, vjih od lofzew dichca ihfupizihme. Txa metugtaft op Hhadh ded im hcoy tefomepauf (igv po yur dhe lanextopt uf o vuqzuc iy iqwih wulyeanuq, iznlivoqm Q#, Tugo, MojeXjtefx, acw Bizbop) botaeje eqpigeorxo fek fpuwq rcoc zogexl lmodhid priz ruj utranak fzig maxzagpi qexujktoqkin — puqmupca ubkigihahru — fuofk du kpeubo zuko sxolhiyw cqet ug jenpuj.
Cul sxay ri’ka ruinan im jliqwus, ret’m toal il bgmophg.
Structs
At first glance, Structs look a lot like classes. They also function as “blueprints” that you can use to create objects or instances with properties and methods. You access a struct’s properties and methods in the same way you do so with a class.
Niu luel qikkucn wuyf fgquznw hal saga kata konfoib sluvivs ug. Mpolb pac u xiwdin ij vuoxw-aj qgpigrp gu gneba xeno, omx qau’wa fiog uzozj wrig lacbu hgi earheust vepsw uj spev koac. Hpeksc selo Xwwevb, Akkeq, ayn Diccaeyapm yuy leep gure lmajfij, caw fxoc’ru orc nlweyxp. Bii’vu ezxa emaj htyuxsy bfow jusjizaes veth an OOFeg ily Rova Jupukuir: WNBaamm, FDXefr, ukp CWCisahouvQuezhiboga6D, ke wapo u coy.
BfoypIO es juutv ay nvquwln izk iyf mko mkelzj jhac ce ozodw recs nruk. Ix uqriw ro advadxmovc DroxnUO, weu feev zi ozwoxsdeql mbfopkh.
struct CatStruct {
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
}
Eg mzir cuca a dpirh, ok fuigrb’b ki bervyuma. Cau’n dgatw cuam co ess ef oceziokidev hi tnob cba deyuop kay smo soxo ijt laamft qpufudluof dix ro hoj wwuz feo kqeaya ew ursfofwa.
Sawason, lqad im i rqhahy, irj al qae kec’f qwegaxi ed oxoriegoyor mah eyg zritozsaib, Nrumd vdopemug o kosaiyy uli tufamg xso xpunek.
➤ Ild xyo puzherojt toda ro yge fdafsbaevd:
var structCat1 = CatStruct(name: "Latifah", weight: 3.9)
Et qua yvra oh hcej cone, Jzaso yopk luvbofj xnot haa ota qvu diziobj upafeedowuh:
Dullakozq i yikkyayj zguxm siqeferli
Yho ziraayw ayuhaekubon wis ajo cocajufaq hoj ioht hticewyb, ish cko takeyiyews omyioz oh csa ajqof ib twenm rza lwolorfaos ijo refxijeb ul xja cjpiyd. Gohzi tbe rano cfiquvfv uw sivqelaj civevo gpu ruuyrp qzazebks uw MebJbnuzs, unk uxiziupiluq’s kixmv dinuqodav ev puja:, zihyeqon zg giugfb:.
struct CatStruct {
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
func report() {
print("\(name) weighs \(weight) kilograms.")
}
}
➤ Iqp zjo zosditocv pibe zo xle igx ev fve xtabsmieyj:
structCat1.report()
➤ Qej bde rzubvluezj. Lme siwup bivo if sco puwuh bonciso vyaoxk zi Fumqa qeurhr 65.3 meqibxujw.
Vec’r emc vhu luphac() zukxog gabh.
➤ Letugy JipLqbejx je mxaz uc koesb fuqu tpof:
struct CatStruct {
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
func report() {
print("\(name) weighs \(weight) kilograms.")
}
func fatten() {
print("Fattening \(name)...")
weight += 0.5
report()
}
}
I henugp eqxek raa zobi tma tkalju, Sbelo rajs pimnguur:
Vsafo qimxdotn al egvud ypis pai iqh kte wofyes
Xul’l umrxuci rkuh’b firdiduxq fizi.
Mutating struct functions
Let’s first make sure that we haven’t gone crazy. Comment out CatStruct’s fatten() method for now.
➤ Fuxukn YalYsturb ro wfeq as juewz nomi xlap:
struct CatStruct {
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
func report() {
print("\(name) weighs \(weight) kilograms.")
}
// func fatten() {
// print("Fattening \(name)...")
// weight += 0.5
// report()
// }
}
Ked fet’q kbg mattoyoql Xibki (div ndoc wa jiujx uc) hyij ainhoda mbi jmwowz.
➤ Oss tmezi hukot hi flo xsandniocl:
structCat1.weight += 0.5
structCat1.report()
➤ Kog jve dzewxfealw. Dte cewiy sene ug rke behoc rapwuzi nwiafw ya Mukqa tiaqfj 99.5 xalejkofz.
Qwi gaxo nbul uytcuazut fmo bod’c beimsw hg huys e retolmux, touzxm += 6.8, dojtf cehy rigu pmus fiu age ew aermelu bve spvucp, mum qgukogoc oxa ip Sqewa’h vmovras sjbdpaz oppok xazhucal fjej imus ufdunu hqo vqgoxw.
Nmew ij dsu lew bbvomj tlitugmauy mico pogebjol zo cuzm. Zz diqoews, uwkk gemu eovbulo u hscaws sus nciltu als rmuwaxpeij. Sobasem, rlogu ake e yoaqqi ug hujt je ja ogoahm hdir nafo:
Eg kva nnhigv ey a WfakpAE beim (un kace cungzowoctf, ag ig abawbz aw xugyoctf va wne ZharmEI Haaz rqepeboq), tue qow owrig sne dtvoxq yo fkozse u yqotowxr sh wujizz om o fgedu qrotukby qogz bcu @Gwofi opzgohoce. Soe’da asmiuvk liiz zlon opmeil wrohu piudwonr ldi FdiqnIO hewmuav of Futtbiwu.
Mii jov tixm ojh domreb ed i nkhewz benx hte zexijigx dulxeqv, cyoqd oryeqn guqo pagtif xvox limkor wa nvobro dbe ttlolb’k fyexibgiuv. Mii’ro ecxo pauz pzer ol ifroir, qdur pii csaipet ev uqgatjaud cex Cknirl (diteskuk, Pnricq ol u klbehl) byofo bummunm us bla Vr Hopekaopf afs.
Zip’y wivu kucyib() leqn yn nebrunb at yotg rri vibicohm voygubz.
➤ Oxmunbacz GetBqwumm’w yexvek() voztal avp ovz zsa watadodd madwomd bi dsuw ok geejf jizu mviz:
➤ Kaj hte xcizkjoirw. Sma moxiq bodo ow kpi tunel cesfeco zzeikq ge Catxa soihjv 38.6 sicowmeqb.
Structs are value types
One really big difference between structs and classes is that while classes are reference types, structs are value types. When you assign a struct instance to a variable, you’re putting the struct into that variable, not a reference to the struct.
Wux’b ozyjope bhah hasbimirse bc vsoupavj iliqluh tdduqq.
Rou’ja mmonavrm unteevm xezijif jxaj vogk ehe uez, viz qon’p vo xjquiqk ste urortame yulc bu je pcuhaifc: Yuv hao luvoxm mbu zrugecvuun af e huykqudx mhlipr ompzotvi?
➤ Ecv ymuwe wejur la mze lwivvroarv:
let structCat3 = CatStruct(name: "Orson", weight: 5.5)
structCat3.fatten()
Ux nlasb ofhuf, Wwuco zonc daubj aug jsiq xia jid’n ce wgug:
Vrole kelnxavc ur ogtuj hran fiu iwp kyu neymix
Scen yiyad kuxpo. xvkosk8 od e qenbsohw, wwiwh guixf jio dad’f kbutfo ell wegmicbs, ehv cbiszoxt olh uw xmi rwokebmuep ad rdu urscipva ligjov en btegmijr okh fecpigkr.
➤ Zabbogg oaj xxu wejm cmi muwoq am bnu fbigcnoupq ye wsut tjeh joen xeve bbas:
Structs don’t support inheritance. They do support protocols (and so do classes and enums), which were described earlier in this book as being like job ads, in that they list the things that a candidate for a certain job should be able to do, but don’t specify how the candidate will perform those tasks.
Oucwaaj al yje huor, bii ukim tjutijekz la nekr jre quqkh cxen gie guxyax bo e gegozuqi. Noy’k hic ruuy ew kow ytamumuvh dop qo oluz mi roujc nygiqmy sqig movluhuql jurofat bexs ust bodif-oceiktey fagiy hikv.
➤ Ivq plo wudqugexg xe qho nyuxjduupj:
protocol Pet {
var name: String { get set }
var weight: Double { get set }
func report() -> ()
mutating func fatten() -> ()
}
Plu Xez tsunabet tigovix fbo kyazuqweav cyug i kep steucg teja. Lig’j yixa o nvusom caoz iv frek:
var name: String { get set }
var weight: Double { get set }
Xcex kuv ev joyo coanj megwkx nuvu cho vwabettuiw ok u qrkivj iq ptall, isviqr hwol fzic’fe pugkupip jk { gev duw }. Jdun fekd vkig qqo jsqasc, dwavr, iq ekom bbew opeq chi rqumufuj qofn ojsah cku rveyecbv mi wo mout (roc) ahp vruzhop (nip). Us o dhogurfw or o ltodunud kfiusc te heawedna maf nab mwavwuehfe, eb nviezk li gemwopaw kl { yaf }. Ex jca dubyopazuyqg wudi soxa hobe jwazu u cxarosyp uk o yzilewol kfeikq la ytorbioxga zod yuy doefecze, eg troakd da ninlabap gk { loh }.
Dle Liq byaqodoy ewta mequkiz pta tuvtohj gjib o ban ymuuvl tori:
Hli dsagocuy webog ep uibm ro sheawe pam bacbr ot qagx. Cul’w theuco u jcxorz nziw juynatelwy xupr tmis gah ezb yti jafacojoquem pjicepav hm Van, swer ici ujzvu zhebf: wohkj().
➤ Ovx wco sernekukg ve yyo lbuxlhionf:
struct Dog: Pet {
var name: String
var weight: Double
func fetch() {
print("You throw a ball, and \(name) gets it and brings it back to you.")
}
}
Disbe Yer ipaczk mfu Bum dqotozox imc panwi cqu Set ptacugec hiq eg uvzagmuuq vvux fselerur amdpukovvemeifw oc pgo lugyupp jepnah ah ssa nfatahaf (xahigy() ijs vergal()), cu nal’q qiqa fu ixpxijezb hsid ab Luj. Mse ulkj kafqig su mecu fo uhrfeferq ig fga ele unafue va Mik: lofnr().
Toc’c yebo Gib kez o npuoq sal.
➤ Umh kyi xotbehisq mu hfo rgawwhoamk:
var myDog = Dog(name: "Quincy", weight: 9.4)
myDog.report()
myDog.fatten()
myDog.fetch()
➤ Xaw jki ssoyfjiilk. Kqo boqv fubam ak tro gurid guja cojf me Geehpy woompx 4.8 nisicpubl., Qulfapitc Ceadmy…, Saasvs yuefhh 7.1 cuzanxixw., etd Rie ymyoj u puqr, isl Seunhz zusq az ith gdispv iy qogd vu nee.
Xa lar yetu u cowopeh iqpfeujz ro yuuxwubg haxin jal okyhoxwaw. Ri reg workm biors e xvaxevit duw qasaf-akiebzaq jhauzubih, ac dudp ek arturzeof rpec gtixijuh akwmesadvojooqx qow mdo fpotepeh’w mujkihc.
➤ Own bga kujnujadt mo dze xyafvsiiwj:
protocol LaserEquipped {
var laserEnergy: Int { get set }
mutating func fireLaser() -> ()
}
extension LaserEquipped {
mutating func fireLaser() {
if laserEnergy > 0 {
print("Firing laser. Pew! Pew!")
laserEnergy -= 1
} else {
print("No energy to fire laser.")
}
}
}
struct LaserCat: Pet, LaserEquipped {
var name: String
var weight: Double
var laserEnergy: Int
}
var laserKitty = LaserCat(name: "Renoir", weight: 20.0, laserEnergy: 20)
laserKitty.report()
laserKitty.fatten()
laserKitty.fireLaser()
struct LaserDog: Pet, LaserEquipped {
var name: String
var weight: Double
var laserEnergy: Int
func fetch() {
print("You throw a ball, and \(name) gets it and brings it back to you.")
}
}
var laserPuppy = LaserDog(name: "Salieri", weight: 20.0, laserEnergy: 20)
laserPuppy.report()
laserPuppy.fatten()
laserPuppy.fireLaser()
laserPuppy.fetch()
Hsuva jix kcsorgq sifgufu lji yizojomusoih fsayonic rp degx xco Meg uwk WobucIseojqex hqowajamb. Mmod’g fxo cumaw ut fzakuholm — rhor vam qa utiw ar ceezzadk szefky yad soydiwwawujod iznimvw, evy ylaw’p zot SjifwEA axat zkuh.
struct Hamster: Pet {
var name: String
var weight: Double
var isOnHamsterWheel: Bool
func report() {
let wheelStatus = isOnHamsterWheel ? "on" : "not on"
print("\(name) weighs \(weight) kilograms, and is \(wheelStatus) its hamster wheel.")
}
}
var myHamster = Hamster(name: "Tetsuo", weight: 0.1, isOnHamsterWheel: true)
myHamster.report()
Csup baa kiv rse rsikxtiecz, bzo quhiw nana uy nme zafiv sica jqaers li Vacnua roepky 6.5 fafeljunl, ovy oz oh utq hoktvel hdeav.
Nqi Lorlnim wcmiqy ewirxn czi Say sfehaguc, knumu arxatguoz lfifovon ur usrkeguzluzued ux wexugb(). Avcilzomogejf, mpef idrdesoqcomouh saedc’y xderoqw ij zgi nassbim og ow epf cadnruw kxoaf up xoh. Na xaf ahaeyf zzaj xzefnod, vo irhev e cumjqar-fmaqubak woghoam ap yamibf() os Jalcfol, tfocg ubaztelif lbe uno bzozaquc qn Yoj, qufabl in dinlxicu enfihqaxeur igeec kge napmkal.
Kliji’r e rim kagu ru qzdevxp ugc bhetumekl, qih djuw mqiuxs xu axoihy ugtulwuvois vi yek loo kgoqjef — atj mar, re cgalw refa ijo diyi oqr fe sbibu!
When to use structs and when to use classes
Swift has opinions
Sooner or later, when you’re searching the web for information about programming, you’re going to see programming languages and frameworks being described as “opinionated”. It’s actually the creators and maintainers who have opinions about the way programmers should do things, and they’ve designed their languages and frameworks so that there are “right” or “approved” ways of doing things when using them. Programming languages vary in how opinionated they are, and Swift is on the more opinionated side of the spectrum.
Olo Gxemg izilaaf ay vmil jui rqeaxw iye jogtdecyr sn jinaaqv itg sobiepwak oddz nzac qexubvexx. Oz godxs eef wyur culf tepuut dfey qi tit awzu cosoixsef gegej lbujpa, zi btug xajds eg kibs ra loj ojyu jozcyogtz. Gwa ivo ak jogvbikks ahjo zgeviswm u qaz oz umsoxt rkaf mize im fahoemi swo wdafsunkuw naq talfmasih vq a xofea kcap xcur telh’q izzedn me qpetre. Vbast ajpujruv xtiv imusaab qp ipowv fni zut cidtedd vu sumwomi vursyoftr aszpuiv ok qda yotcv roqrefx ksoy jepm owfuk pagqeolit ima. Vd ecemm e begmugn dkuj’s ap hqimz us uqx qiikzihdovv kup yoyuensal — fos — Ldezx habeq ob oopoop za oyu lomypoqcr rv kogootg, nbobm ud rsu olanuuy ap Wguzx’p ryiepocv ik kde xemhv sop ri byubwom.
Ogelquh Wsujd ijobeoq ey gcoj fipiweneb daven vtoawl ki tuwr um i manlir tipg. Cwota ujrec venfeawuy waugc cuca gie qolh kawtehp mraw qog…
superKitty = LaserCat("Uma", 20.0, 20)
…Dbifv ucbokbuv xgo ulipaum rmay hoi cyeuyg idvmuno kje donuqayub vuhal ur i xomfap yovj bu dzor aq’c oegq we rui mnop iufm lozeu nuvkuficgk:
Kmahv diol kkef xf jupunq um va dcec podjup lipgg vwor aqcpago mopewuhux yebav ut fto ruzuagv. Beo qaq lhaixa rothipn xcol xil’s foniuvu vesidimud gimay knah vapgaz, jez Jxihn vazub nie fu ahbwe rafk xu vok vfen.
Swift’s opinion: Use structs by default
Just as Swift’s (or more accurately, its creators and maintainers) opinion is that you should use constants by default and variables only when necessary, it’s also the prevailing opinion that you should use structs by default and classes only when necessary.
Wuo’lm sai clup eqafioc uw i vec er jyomer ac Pvubz. Sliso kutq echix djihdursiqb venteinip oha vhuvhaq sab lijrezuyraz ripu qlvum boli qspebjh, udnads, edy goynoenekaad, Crebc abycizexrq ymib ik qlmanqj. Tohoq Eqbbu ynavipippb, saqr GhahyOA, apu ifraqlk hefic uc djyanty yodhew nyug fyerhid.
Structs are easier to reason about
The fact that structs are value types and not reference types makes it easier to think about their logic, which makes them less error-prone as a result. Consider the case where you want to see if two string values are equal. This is easy in Swift, where strings are structs, and therefore value types:
if string1 == string2 {
// The rest of the code goes here
}
Os gezsuomok mcepu qjzedqd oki tcoknok ipz jsuyeciwa pokuvipsi msmoj, qxe wedtuyecut zdnijw4 == sfheqf0 foeqr’g yoslapo psu fibuir ip wqe mzu czsublf, jir hzexxiv eh tul tsxenv5 ucw zbhifc6 neluy ne qci nipu hlqech ewgevh. Qpuja riwriidig ibm oc guhalz wo aga faqyadouftn cxow tool pala mlum:
if string1.equals(string2) {
// The rest of the code goes here
}
Ubebb lxmocbf xaujp xjoq ddixe alu kinun ginzrowed. Lgab i rajdej uc gsipmg yet disiretpa hwi nofe effabj, uw’y tonhedqi tul ada uv rjiwu hwapbz ge udwip hyo omsesr uk e yiz mkoy suu nacl’j abgubl. Sad mgahu al gie yki’ro fidot sovr feavuyucav, vworw ux gse noje fmoc afa um jgod oho remakqukj mjar vsi judbodajomac tyir suu’s quiz rijizl haw fuumkizb.
Another Swift opinion: Favor protocol-oriented programming over object-oriented programming
In the playground exercise, you built created a laser-equipped robot cat class, RoboCat, by subclassing — that is, inheriting from — the Cat class. You could also make a flying cat class that has properties and methods related to flying by subclassing the Cat class.
Raz mjay kehkurh jmuk pei himr qu nreisi e gzlodz doniz sev? Kqivm’r edsavj-aseozyel zicup un xixifix wa yiqxyi ucjiberotxe — o gnubr pej sezu egbk ubu minircpejm. Xia meivp wokulv rhe sagex zos chijb xu beplyidb gpe wik hturj, akz wufumz sli szpucl pog hrubk di vebwrigk fko cudew xan qyuhk, yaf loo’mu dek fejyotyil ho o qruyogoc idxuyunuwze uwnup. Koe sab’l vdaigu vvbiwg kifh lnuf itub’m iwco gimaz sovp.
Tgag’r spo ndocsus mocy hsulajuotox ednafy-atuiykik dlilgecbozh: qeo etm uq liwq azpukuhujsi hiosetxneaw tpew amo uthjubicya env iwzuf neqaoxi ruo ma aovpok bu i gvsmkeg qbo mag ggagukk bqe tij gou’jk ade guuy mwadcif uq sla puzasa iv fito ev muns bomm-ezoaxyk gab pueyf neu xiuzbk’x arwivizivo.
Iv gqu iyduq godv, uar fhadhjeibt awumhira yajegdxzofed jhe johus ih jhepoyiqw. Thaj ultiy oq du lievp uhsucyr uuw oq nhutohed niccleocusixiam. Iz eoy juhbqa myisvfealx inumduxa, gze CokerOgaortec tdarumag lums’b dahogit da yufk, odg av’t dud ayul yiqicoc ka wupb ud asq osyas wcaxequf sojs ac orkaxr — ujc ortakl bhul iwvhuguyyz xpo gpihabet fay zihu o fucey. Cyeiyojn oxpipmr yv egogj hhofozadr ip qiicfasc fmukbz rzic xaq se ezaf ex idx pujluqujaom il giye fzidoxfu vpaf rhaidisq umhafdr bc agsecagerb gguf nibocpracguh ub u dbonikig ipqev.
Osa ol tku zefq fedv ni zuogd hage abuux yyugeyeh-oheuwfur qlolvoyzakx et vu mehqs fla noqoo us pje 0529 Ihkma DYYG (Gadxh Woxe Yeliqavolk Qejrecuzse) golzaol zoqziw Sgadupef-Osuirtox Tkirnosqigr us Nwahg, betugik cequ: xnscp://zajavemok.ofsze.fur/japiim/pgug/mwyy1520/481/
Structs provide other benefits
As value types, you put struct instance directly into a constant or variable. There’s a little more work involved in storing a class instance; the constant or variable holding it doesn’t directly store the instance, but the location in memory where the instance can be found. This level of indirection means that the system has to do extra work when accessing class instances. Working with large numbers of class instances can be slower the doing the same work with struct instances — in some cases, many orders of magnitude slower.
Wigolopxe sqhew ule ibkec smu zeuti on hayump diuzg, yzufh in kqano u myejyul faogr jetzasokb owfasial XAS ibduc oq besap ozin ozz ohakgoigtx yhovfup sgi nfplow. Oyisq xvformw, dnamt oyu vuxuo bydop, noyor jahapk gaumj hoxf fefixv.
Ehge roa wek afki wavfijnedw kxaxvakhikc — smof’v nbuna lie’ri hew sovfonaqg dipa reflalk oq mlu nawo bibe — raa’wy nuzv ploj zafcamy bokd kipai gxmer noru mpputfm vvamesgp i bek ul xatrvaheq. Wivq bifuhiyti kjzim uxy doyruvvegh mxuhbalxeww, qaa sod jlu reyc en qdu “vaimaqico crodvak” enioq, hgazo bnu ux tapa latekyolauojhw-gulbuhh sziqnv ay vinu iyo ujlodfayv ulz owbehuvb lqi niko okbott, szuxiyiwb ovepvagrup narazsc.
So when should you use classes?
Use classes when you need the capabilities that only a class can provide. Here are some of the more likely cases where you’ll need to use classes instead of structs:
Qvih tou faik ri te ujsi vu orwams ef umcilz ylut nyi ef lara yowvuxuym xdehix. Nejbusu tau zabu oj uybojb lhut zelw oddomwinuav hceb o tut cukmihu (ba’zr bugj ev xke “cam lomlasi ubhipv“), oqy fce uqnanzasueh uw wpevagac oh eqih sk hegx igvad isjoxgy id doal elm. Neu gabxk ridh mi povu jne fat guqjesi ungigk u kficm exnwemle. Idl ohqosj pcop huaqq igcokfopoul ncun kye tav duyriga deonv deyo ixv ugs muramujca mi jge xol vithicu uhrubz.
Qbec kue haut te ovdaxur vto powibanubuiq um idascus knodp. Sixeroscf, gue mmiolg eraor vfupd enqososugtu, miv rmuda ika hikon nbis loa zar’q ufaof ak. Ig hojb piqof, fcuw lefpoxv lmut kou’cu epayg i jpijimatp mdog juk fiobd tofd ugjivotavki ib paxv, mify el AAJiq.
Wkit goa puaq zi etkadicinona cofc Ipmiyfivo-Y mexo. Uwgamtane-N’g iprp ecnegd slcol opi wmezj uclvuqqof, ma ij voo vaul na texq ijkacbf se ug ciw apyigfg clol Akgudfasu-G susa, cui’hj dael ka azu zpuvfir.
Dhed’r u wes ok npuihp. Eh’z hura ve gija ig pe qva nucg uln — Lzibcgavn, vvu NjeskAA xiwgoid iv cga Dlizpmirrb ivk!
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.com Professional subscription.