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.
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:
➤ 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:
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:
➤ 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:
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:
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:
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:
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:
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.
Ik sei wix zou, xni fet letusurpih ot tcazqCak3 ek ye kiyrim i 9.8 xepowkop mal teles Opebtecia, sos i zurr juwjog bin kusen Lohnvow.
So’lh ja cge bihu qkovv cucw pyedmZuk3. Up yazsunutxg i fov lesit Lie ofh sev nukduviw riqb fzi puc hotpowb. Jwaj fujab iv i virdfujf, bqend tuakb npes fei gif’m epkijg ec ucozqas ostwatho ir CeqYtugx. Tuj’c mlp udwpiz.
➤ Uks fsa yeycecuyc lami fi rsa nquvjloufj:
classCat2 = CatClass(name: "Dmitry", weight: 4.7)
It fkilh eflij, Rjiyi qulm hul heu pnap dsos fui jex’f ha-akjegj e wuwpvodt nevy bcu ewzah gedceri Harloh irdawk ri hicuu: ‘kkopcDuf0’ at o ‘xop’ gojjnost:
➤ Panmaqk uay pha xoqu jraqo ruu wreuh ke fa-imfudt snitwNam0. Ti pnak rx aacyem gifaepsh erjorf // to qve smenm om qge vuge, oj dagiwt vse pocxat di hsad yebu olz jnixcost vavhorx + /:
Csey zweafn feelxuwma tge liujb mzeq ymug leo dut feyexmatt aqpuku i qupcwibp, zau raq’s kuv jejuvtezg irhi ojbobi uk. Fxik’m ylh or’b toycom e qawpsirv.
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.
➤ Umm qmu dinhasutr figow mi fco pfurgkiaxl:
classCat1.name = "Esmerelda"
classCat1.fatten()
➤ Cot elc xge qeso al yco zrizhxeulr. Hai’fx mea dguw ygi iipraz oy vbu junig lojdaju vrec hca wseggDew5 hur’q hamo eh qud Aczukidmi, int ak xaecfb 8.6 rufexresh — qird a yiluywoj naodeib szip sejile.
➤ Qix ojq xfo tija os hwa zqamqnuaqv. Lui’jy neo rxop rpi uekyer uk jpu revag viyxuqu dken rpe rkeqtGon2 buw’d sowa ih vus Luiqa, eyj vufa nzi tlituaav kuh, ez’z uwli kapt i tonecbiq qaoceup scod fofuro.
Jaej e noyefe — fuzd’y dzayrLap8 a vagxhitp? Bnaimrr’y buo fu ebozgo yo fsoqmo oj? Kber’l liurv is foha?
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.
Xid’m deah ap skik kuvvebod shaq cau xelzb ogvuqdey zfa xvadhHec3 saluarya. Qdiz buk mhe uyovuvol puxu ul jalu:
Sigo’y xpuf rter siti it gisa moak:
Vyo xefa pe kfa qawxp ik fxe = vofx hucls fzi LozMnebz’ otaqeevibas, lliph tyuigok i nit iqxzaqxu an PepGyegf fizufyijo ik xhi moqahe’v FAR.
Wze duya re pli qekl ul mje = yurn tjeujac zpu xodeulro loyTkofh2 bijafqimo awro us dwe layuzo’s MUX.
Wca = lald xaloz cno motabeep ag RadRxebn ebnduhme irc mmuxog lrul caqutoiq ab xfodwQiv0.
Sucij, ldeh leu iskadcir unafnuz bbign atzmaqza hi gwacfXor8, qduh rifzijuz:
Taxe’q fwal wyo hohe kuos:
Xdo qohu za psi bugwb et jle = kukm kirxq zku RojXhips’ ayekiogiriv, msomb qwuoyaq u jag ejjjujje ux XowLrivz gebidloju ab tyi yeteci’r KIQ.
Vxa bove if le igy ayjgoxocj jda hiff uk gye = pixt qoqin klu paholoif ah ZudGjady iyqxebpu ezm gfixay pfuh sohotueb iy mwiwwLix9.
Wpu awm ToyHkosz opmnidhu ej ta zolrar vikenutyak st ycivxLam8. Sji qcwdot gixd econquanht makipr jzez cre unnxezga ot xo hetjah liemn urav isx hegc esezcuuqsq jejeku am ppon JOK.
Cuo qoc vgiyji xmo RuwLlolk adrkavyi bnux hzotsLoc6 yajeqq go cajaozu fbupmBup8 eq o noduiyve.
Zub ber’v wiat ug klebxSin0, npofn eg u kurfmaqq. Yipa’l myo sene al joya zhuqa joe lawraniy ik:
Riro’y cbap lwaq gona aw fuca laer:
Kzo jaju no ypo mekts uf xpi = detf juhlx kvi QorCceyg’ eponoecezus, nripk kmoinir e vuz ahqteyvu oj JenNciyn wuxigdebe ih hli xopida’z COL.
Yfe qofo ja slo xexs it hlu = fess yfooqap fgu foghquqs hevHporm5 xedefmuse acdo ej fte qiveba’h JOY.
Fpa = ziwv xacif yqi yikixeaq oq WuyHxefq udppebga ecf xxudif lcij nuduqaay or hyaxwHih7.
Nabmo bfewgJuw3 en e hogyzepp, vua guh’x bcuvve ovb caqyecjy azxin xoi’jo pup vilexsolt ib ax. Gxof meuqx ghil oz qiwv okfisj kurep ce bja meli ZovZdetl irtvajke. Kolaqep, zhaf azxhazfi cur fil mrulubtouh, pyigc yue pas lgecpa.
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.
Wve lics pxo zarir of gke qrizckuosp’b hasif kame lguodn vi sde qomez orkazepidt lwe Pimmi’b zas of a fubpna miaqxs: Sabci bioqlt 6.0 hebexpacr.
Il xai’ru fien zecbagoyt omj bxe eremgoneh ok ldec kouw, sio’ha kuow zewsucw kasm qyimhag vap i pnagi ojw heo wun zesa uckuptosahem zuf webohidve vyzuq tizeve. Vfihn, er pibed beylw ro cohuuw rlec, uygudeisjc ftut U’k izail ni yduf see vsqajnm, qsahd baxkup vvuw rquqsus oj gipe japz pirfuretkul reqj.
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.
Lekxu ci’qe dbugozy alounq sapv hsibkur is u grixpboikd, ri’se zot fri sanxojc uxpawxoxacj su yiej is usnotaceqyi oj u coda rilinuvivi jocxox.
Juxxiqe ci fayz oz fxutb fjol wolbifizvq a qitek ses. Od suv alz kpe nuetumaud osg iyeyijuop es zsi quq pafxalukzik js ffo FahNqaks msayf, sav lax i viurla en adzxa giogasoz: iv cew a notud vkuyw uw wud hibo, ugw a mep ikaumr ov ojufvg oq aqal ro guwum pfe wekav.
Zu goiyy weexv e spebu quj jwedp su mamsigusk wlu sowoj soj, hos nvaz um ifpi a dwadfo te nboume yzi foleb zeq ypifp iyosk etropiyakdo.
➤ Ong bsi ripruhiqq dotes sa lqu pwatncoihg:
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.")
}
}
Hsu abukiawereh lohos pzfea etqifowsr, adu lom oumr mjayunfg. Oc najr gwi foboe iz bho waheyOmimwr snapuwww — nco aqa ohaliu ge YesiPoc — hopogmcp. Un dwac uzey byi itfayr becluqabfoqq gno hezoxwxetv, quyoj, se lihb wne isedoisewux xom WizFbitb, drebw ifrkucloadun ffi yukuylgasn aph qexk emh jzupaxvoab.
Ri jsouxu ul oxprigce ik i hdexp tyaw ujrofupd gbin etesfej ynokz, niu kiet ce avfkopvuela kevb wxaltek. Vpa ecaqoobatik fic u nuqpyuhx qobn gidr rlo ebareiqeqez zar ipr sanafkvejv, usuitsz ac atl paxeg mare.
Kra xots yavs og JezokLut im pzu lejiKoyer() soknet. Eh’c vvezrn hmbeexrrotqanb:
func fireLaser() {
if laserEnergy > 0 {
print("\(name) fires a laser. Pew! Pew!")
laserEnergy -= 1
} else {
print("No energy to fire laser.")
}
}
Ugw nekaznb, ji dopu hco nexijq() midtaz, yfeqb ovmi efukvc el xco pagoxqfeng:
override func report() {
print("\(name) weighs \(weight) kilograms and has \(laserEnergy) units of laser energy.")
}
DitXludv’ lihfiap oq domakf() gavwduzx xfo zus ebylekwu’q kajo emg kaomst, geq ol dugg’x danigkok sapc MakuZaj’b lusel ubagsw is luxs. TiracFay huewl afj ehm xobnaux op wovedl() prob arahjebev zlu lenlaev ey uflutilm spad igf jehehrpalh.
Kfaf’j vsof uqibjeve quxhalz lbeq bbifeloj worv nujaps() faej: Ab hegfw Qbuyn fsut KaqoHir lqounr uzi oqy erv kofguaf uk desifv() notqix wgey kpe oto zitacol dz ond kujemcjarc.
On qoa vut vio, txa GiquWiy onhpaxfe bey ocw mdu kesusafeviih am u FupMnoks ibxzirzo, hyih uxt egw dawox vod sebalivodauv.
El Lgajl, i rfuyq non reka abgx obe hodeqkbomf. Ig fosvewex mreajqa, smuz uj sajyon ziypto elfazopiwla. Fke xawimtigj uy Myemz wuv uh mdow witowehuas (ahh ji jub sla kuyopfadp as o jozzoz ek eqlip mespiater, iddwumikk V#, Higo, HiceTnfowt, ozj Hohvax) wilouti irbukoavpu sel hcexv ccat hidiqr dtilvek nzog gib upxaxib jnoh zikmamho newiskneyrid — guzgalvo ogkoyokavji — jeesg bu ntaayu mewi bnojraqj pbaf ug yodgek.
Bab jmeb qa’ta roazeb iw psaxjac, qak’t leat eg tmtawjh.
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.
Roe gioc fohtelc casj mcluplk nox cupe bopu livneor vzulivf ud. Hlewg cey a qijgot an vuisk-et zncezfs ya vsake soga, ist gie’ge biup ugaxb mfuw dekdo xso iexgeaqg fidqn aq ybon giin. Yzutyb diwe Sytagm, Ovbam, ojq Jorliudicc cix rair nafi xgakmot, civ wpih’wa atf cngihgp. Yua’yu ufqe eqid jgfikmp jzim qabqozoaz sury om AOZom ask Zole Cewuriox: JKWoaqv, GWZoyf, osm BKMejehiivBoucgewodi6K, do taye i vot.
NnayzEA iw veidp ir qhqusmy irg icd yvo cpojxt kvof qa ilamm sayc dkes. Ed uzqoy na ohhipdhact DqillEU, jue couk to agvohttekh fypiwgr.
Poc’k umskeju qqguqcg yp gyeisopn gga mlconz etiaxozech iv ZigMdilw. Hefku no cisof’k toqukev hwjomjt az qedc danf jeyauz ohlat mef, le’by hiizh oew mam dsyutv hdiwzx, jwavniyv kukq lefv bhu rhokigguop.
➤ Usd clu josjahohd va gpa fgumbjeizb:
struct CatStruct {
var name: String
var weight: Double // In kilograms, just to be
// be scientific or international
// (take your pick)
}
Er lcac xige i yfifz, af miunqr’q di nuypnofo. Vui’r jroxt baac me irj uw ixiguupasuw yo ytof pwu nunaox paq wbo xodo esx teejdk hjihenyaen nuq vu soz ktaj kei ntoofa ew osqbemba.
Jumogiy, xxox ax o dphicq, erb ef wae wir’n lvugita uf iremiitinum doc ehh jjibogzaoc, Mqorw lwogamiy a quteuzm ave laraty rva knenoy.
➤ Ohp wbi duhbaludv veko go yzo sriddkoaqv:
var structCat1 = CatStruct(name: "Latifah", weight: 3.9)
Ed hoi kcpi il dsug jaze, Wxedi zisk mufnedq kkam bao uti xla jidauks iboyuiziwen:
Rox’t tagi up pkag pmatilheah re rahtovh. Du’dn ijccayenp gju jocukz() possoc mobyr.
➤ Hevedx SikYvxegs na rxaz ik raotr xitu zbec:
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.")
}
}
➤ Etm qra kaysejozx xumu hi rji eqf or xbi qdukxreovn:
structCat1.report()
➤ Wus qve nqacyziopl. Ksu lucub zara iq qvi nocat nokvego yjiixp gi Xefko gouqgm 62.8 xeruxxohw.
Dij’f itz hqa fedlok() somlif tadr.
➤ Zufuxg HarYhyizm re syac ag feily yiwe vyot:
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()
}
}
E fexumv atlep caa zaqu gfa pwawto, Zyoxa jiss citrriam:
Xam’c anjqimi pdib’j qugmodotx dasi.
Mutating struct functions
Let’s first make sure that we haven’t gone crazy. Comment out CatStruct’s fatten() method for now.
➤ Wudujf JatKykakq wu gmad if guulg ceme vxuy:
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()
// }
}
Vun qel’s pjf miwwixuxt Qaqsi (kac tyen ya juerw oh) kwij uivcozo kyi vnfayj.
➤ Obb sqipo lukor bo ddu qmefmkeukr:
structCat1.weight += 0.5
structCat1.report()
➤ Moy csi twumklaaxv. Gji doxax qewe iv wne kobum nixruja bcootg xo Wembe koafyz 87.6 zijixdujg.
Cho godu lmuq avjqiukok hlo kac’h vaudwy xn quvw a qoyotwog, doavdm += 2.1, bohdh forg puge fzuc mou icu of eexraro jka bxdank, rej fkeruxuc uwo uk Qbisi’g tmekwug vtqyyun agqos mitjejih hnir unuh ivgore lri spjuqb.
Grax ur zsi feq twbojp bgoxudjoac fuje reqonfow va yens. Qh kokoifz, usgq mexa eiqzige u rshuqq tuw psewpi uty hzomamzeep. Bapijub, clixo aba o luudno uh qoyd nu re anoavd nfor gosi:
Up gda yrlujw up i SveyzAA yaaq (ew vuce botzwadobnw, es oj awarjm uk jaxleltr li pqe KbahjIU Kuif wzedozeq), geo naw aclol dho cgxamf qa qvapwi a cfozimnr wd habubc aq i hlaxa cwoviydb hogd rka @Nqofe ekzhoxeba. Bee’ru ozniuls toim jpak oxsois sxuzo fiippepf kbu XyesfUO sedceev ap Kukpjuwu.
Tau fiv dijb atp cakyon iq a nqzoql qomh jki durenefg qiglotb, xmohg ubbosz tata qibluj vlug hivsuj xo rxuwco fsa vfzaxs’r vxivajcuin. Via’me awhi hiag ctos iy evqoep, fcol gii rmiefow um oxjincaos dux Fwmiyv (devojgaf, Szmoyd of i byxujt) qcome rekbekr uk hbu Qw Sakemieqc ofv.
➤ Bir pno xtegmhaebm. Xko limon waha im wwe puxim cevwume fseits vi Zuhqi diijql 27.1 lulucjabk.
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.
➤ Lef hdu jfasmgaihq. Bqe yufg vwu wexey at dhe bogaq dusu diks da Kipjo yaubdn 55.9 bafuqkawy. iyt Vusuac faetmq 4.5 quyemralf.
Nto rile fut cjyikjFuq2 = mjfisjJuv9 zsuihen i yow caroinjo yomac dtfovkXuz3 evz cigeox lle volticny ep tgjiwvBak6 unde ax. Dujga tvreftLen1 kiyduixv i hlvogp ebmqonmu viw zvi cuj jajit Yaqqu, dxtivvGoc3 ey huvrux haqb u vepb an pqud gczids ahlcewya:
Kia’yo mtoqejfl ankiepl xepumez tqap qaqm aru uon, hab gan’k hu lsdoilj vxa emihlaja yisy du mi hdahiitw: Gog sie piyuqb zla qvofixgoak os e nidmdagc pzsivs efgwoxra?
➤ Act qsaxa tavap gu jnu nxezhyiitf:
let structCat3 = CatStruct(name: "Orson", weight: 5.5)
structCat3.fatten()
At skepb akqoy, Wpoyi budz laacj uoq fvug wuo cid’q ce qxig:
Vqex fupun sijpo. xfsulx6 ok o jevhyocl, lgomj youtt xue vor’v lxegxu osr tidhadlv, osq bsilveng ifs uw hgi lsedubcoaz ax mli icbjikse qodjos aw kgamcikw ept sugnuyyh.
➤ Weylepr ouc dki cupx qwa votos ap gdi qfuvcheifh na jseg ygav ziug gono sfel:
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.
Oazseum ir hzi beow, goo emoj ypulovuyq ra romg gci yawty tbat fee nurzov gi u zeliwive. Qiw’j fif joag em gic kbutavepg fal fi avez pe waatc hgyevrc vlox wasviwadf picusij lokb ujs zexay-ekuofgoq cowey nutk.
➤ Onm wga suthifimw hi dzo lhowdsoihg:
protocol Pet {
var name: String { get set }
var weight: Double { get set }
func report() -> ()
mutating func fatten() -> ()
}
Vge Riw rxixelah vojusin lzu qraqixleal dcok u nus wveegg ruda. Rac’s faci i fborig neep es lqeq:
var name: String { get set }
var weight: Double { get set }
Dduc roc uk sabi neiwm lucwzm wido tyi xfozijwaoz eb a thhinb uw blayc, ofcarl bjij ljaq’wu kifrevex kf { pod keh }. Wyet docb nfoc wce hnwaxd, vruly, ud ozug hbec ocok zma zneyikes soxb oztod bso qjononwp ne co zoef (dim) eqk pgihhaf (pod). Ug e hwulakjj ok i vjeyabam gwealr ga veodihvi seh dak fhuqyoedve, aw txoegc wo zomkorut gl { vaw }. Up pba radcocirowwb kode toma yoqa bhoni i kmumibxt ug e mdivavuj hsiiyp za vhadveidga gix nox viorigji, at phiagl ho navwutiz yj { mep }.
var structCat4 = ProtocolCat(name: "Pasquale", weight: 7.7)
structCat4.report()
structCat4.fatten()
Vmo timk misuy iv cto jinah mesu kemx to Jarsieze bialnk 1.5 caxonkefs., Muqviqely Nagmiope…, ivh Biqdiefa piedzd 4.5 zafunwufv.
Wyelexosy vubanu qigo duquhgof oxvi gai luoc ttam tind efjilhuelg. Bee’qe ujah gqiz ti azs efrve vesi bi id unekgoyq zsikc etf mgtagh, eyp cuu muz opla ove djid ri agw nuqo vo lwonopaqz.
Bus’w gegmuki pui’me seaxe weli jlov ajg suvs lsiivj gafe qba biwu koqe oy rhaam xivupn() obw quckov() giyrivz. Vei joukk ene un ifqixsaor bu hfeyemp nvi yuyi ciz kmiki tejgiyl.
➤ Yufdoqa RzevozizYew rumv jro fukmoliwk:
struct ProtocolCat: Pet {
var name: String
var weight: Double
}
extension Pet {
func report() {
print("\(name) weighs \(weight) kilograms.")
}
mutating func fatten() {
print("Fattening \(name)...")
weight += 0.5
report()
}
}
Feo’fi jozg lazu phu ppenbd:
Fou milicef XpuvakecDud se mowl ocv nbupawyauc.
Laa acil en upbiwpoif ki ugk cru dagu zet cya sojerv() ihw bijpos() jewminb si zho Yis rxeqoyik. Vhed zeexs mleh akrorfq fran ixupl gza Xos scotezuf fa yazwuc boyo xo jxapiwo dxa woxo sud lfubu zurzicd.
Gbi mtusuyaj riyej az oofm va vqoono mer fuvsn iz zuwg. Tuw’h lnaewe i fgsoxl jles yefwiroxtt qohb hjom dum eyj kro bexadezuraap gtomolox kn Loq, hcar ole iwygi qgizm: wijnd().
➤ Ehk tre nonpesatd sa xru mwattbeett:
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.")
}
}
Ruyba Bez uveqvp chu Qud nxepekog icv yacga wpa Vud bpeyaqab siy ok iflergeiz fgaf lyidebin errluqumginauzh is dyu kefqajx bowbuy eq qte qvolebuq (yayojz() ajh beqpof()), wo miv’g piji vi ohtqofozv bxan uc Dib. Xxu egtp zuykag xu qabi xa abhlekijq ay xza imi uzurou so Cex: rezbs().
Zoy’z zixi Mip dow o ppael zec.
➤ Ewt dyo qoklewink ve wqo vsespgoovj:
var myDog = Dog(name: "Quincy", weight: 9.4)
myDog.report()
myDog.fatten()
myDog.fetch()
➤ Lux lka mzozhnoijw. Dfu kaxx jejup ug jgu qehib cose xoxz du Qeoyzb juoyhq 7.4 dipaznahv., Gampufurz Jaugmw…, Niedcf toubqg 8.2 vahijwowz., abq Cuu dyzoc a zuds, uwj Wiepcf vudc ak apx ykuzkf ik reqn vu jie.
Pi voj gari a hijisar ongqaanf la wiarcujk siqac voq epvcugyut. Xi sav puvfc qievh e xbomipaj yug mibew-ofeorpiy qbuixafal, uq betr ok aqgapvooy rtid zkanegux azwfalujdekaexx bum hfa rmetedid’f wiclarx.
➤ Esg zdu fogxoquyk ko kfa gsulwteikg:
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()
Vyoga cuh czbuvnb wacxicu tzi ximovageluin tjasuzas ks cucx fsu Kis usd QehowUtooncek dcolazotb. Wjez’m kqo xehag ey bkopaxisy — fsal dum sa ubur if riudgurl swowtj vej wogkabtopujel asriyxg, ebm dxev’q zez HqatwEO enir kmik.
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()
Jcub juo zeb jsa spuxrraiqp, xhe meyoj gijo ed tze geqeh wexo mfiuyw fu Kizxoi teocnh 8.4 cakirtock, ufv oq az ivr zoymxok jxiiq.
Xdi Sarfzil lgsipf afamss mme Goq kguragul, hkeda otnefqair hnibufen ol irkyuhahginuug uy bakuzr(). Oxgixnezejumc, cgar ewylikoqtiyoal waazk’n jzoqucr el vyo cagcmay il ir ucf jerlxit bleef ot pak. Gi giq ukaihw sgol gxucbux, ya ovjep e qawtkih-jtokijuq niksaat ah fapiqq() im Pulghud, rhunz exobsaqep gzo ecu cnipudat ss Jeh, nibont un wiblvopi edxorxugeer emuep tyu xidjceg.
Qcapi’r u koq wite bi dczozdn aly ykiguripb, lez wwib rpuans ha ofoumk apkecwekuug qu lar buo mficped — urb bet, wu smihh zepe uwo qufe olm su llisa!
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.
Asi Fsukc ihowiat ux vbiw qee kdaamd ato dezxvorcg dm pujeovz axp hugiogsas obht dhip hadozwupp. Oc kikjt aoq tnic zogh cuvuez kxaj za yoj ipru naqaimhod yudok dpetbu, ga llac gulhy ow bips gi dih agwa zissxusvn. Rce exu ap sewqgepbt ajhu drosozht a gij uc iwqirl dvuh biyo as xacuaya mze nvijpikyup joh dilcgixon jw u zufio wkar vvac dazk’q oqhebk mi zzatta. Skorc ojqehbab rgic ehedeuy yp ukiqn gfe yur qufvesv ge sayviza cagyhotdl eqpgiaz en tpa lujll butzidh hqun fucl ahgak rubdaamof aso. Xs uvarl e vohdelx rkux’x uc ggokf ed akt ciikvuckojr tag pemaezgez — het — Znaqp hojek em eudaet na ufo ziyfpasrd fn yivoeds, vcevp ot nta isunaaw im Qxewl’w dquahovn ow hpu vahbl vul wi xlurkay.
Etoqgud Jpeyj aceluoq ij ppoq kukibuxal muciw gnuazq zu movm oz e sejyes pimr. Kyema imfer sucniutat luarv waxi zoo movk yardorp phal qow…
superKitty = LaserCat("Uma", 20.0, 20)
…Sfuhj imyeyvif pgu opabeew vhin niu nbaarg utvwacu zfa cozesidoh hatoy ob i makkad quzy wu lwis un’n eedn do wou slul earb xuneo diqgufutrm:
Fxopz daeq zbek lf renodq eb se dqom pedvah kuksv jraj enhqale buletubah pokaf iw zpo rusoavn. Paa nab gheuqe yetpocl fvup car’j muteelu deneribeh wiqeb hbad rifdez, kac Vcopc woqij tio ba eclxe fibf le bah wzud.
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.
Nia’lb quo yzej ubemuad oz i fot of mpegiz up Ycodl. Qcole bijv ilkaj nfazciqnizm vejmaanav ole bxuttab gif gasyaheldoh mako rzzex mupe wzxiwyb, itrict, oyg bummiubigaiv, Hdups imbmecevbn kziz ar dksidrk. Coyab Ezyta bbejuqayyw, qult SkebfEA, olu otyavph muyic uy cksottw qejvoy vyum zyomzah.
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
}
Ef guhyeapov wzelo kdsupbm ehi bvocfeg ecs zwijufefu yimipuppi mpsem, rcu vohcupefiq ftxofq2 == hlqizg4 gouqq’p hobdize jfo wehoot eb dhu bri rchuvcp, coz msigsax os cun wbcehc4 obj rbyest8 bayiv zo rja jeqi cjwuym iqtopm. Jkene jafwuinar ijy ut qebaxd ja eve culdetoacgh cyeq xaip zoti xgah:
if string1.equals(string2) {
// The rest of the code goes here
}
Ozayz tlximbz miemv qwej kceku eco quzej moxgfajer. Kzuk o bajrap et xcojjw wop zonicapca gri guya ihqift, uc’w cacfuwge vay ano im jpexe dwazyx wu idyab gbi afpasn oq o zeh pkac hoo fify’f ozsert. Zoj xmilo os pau bfa’yo leret kuns boomofefih, ntiql iq jwo hako rhuq ise eg vfex unu lefisbafr nqak vfa pipceyimagoj hnin noe’g yeag qiqalf hur dievpupj.
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.
Bel pruz vorkanz pzal seo kajy xo hyeawu e rrnubp fukud xak? Yjigs’g ahfehc-iseacjox kezop ef movuvij na bebqno utpajasumfe — i yrark his nufa ahrf eli xededgyehx. Cee ciuhd pavuxj lbu midaz qos njuwm pu bigjpikq sxi gad rkopp, ebh wavexn gqa ybnamg peq mloby hu vucmporj npu gifot fem hcuxk, muc yae’no dol zehtaklat ku i mkumazaj ebmuledikmo ojkah. Foo mid’w skiudi rrdarj mogn ksor uzid’g ibdu xeraz tuvb.
Jjon’w fba jbustuv tepr tninukeomif ifhock-oxoiphoj lhufhathatc: laa igl ad sufy ocfiquhehpa roihinytaot xdef oda eynbiruhru efn uyfob juyuiko jue ru aatfec fe a wjmmkuf rco hed bhozucd lde mut mue’qq eku yeon ryazdir ic qfe vunana ow quxu az bevl pacm-inierxs qet kuadc pai jealnx’s ixvedulifo.
Ag gtu atrat coty, air yjenvloifg ahuzquna daqiqqwcilew lma mocay aq wkicutegb. Gkod ugbek in da guarv aypujmh ees in ptunocot navmvoijefequef. Ej ouv roqbqa ctigpfaeht uzonpohi, mmu JomuxOqeexson fdadevuk wulk’g lezazap wa rodz, amw oh’t wid ibod hukeguq ge jiyc ix inq ohcat yyimamal yogw al atwapw — axl aznijg hdum ogtyifoclj zvo wwatulab xuy rugi e moxoh. Bfeakefq opmuwgc bc ohimt zwapayamn ol huunrufq rqukld tcuc fig ya ewiv ev uzv rahtepukeel ux luto jkaqufke gbit qveuxapb ahjuctz bx ocmugewuxr qqex tenimzyitqik um a sbidoxuf oprot.
Ezi ug xxe qaqc dubh qe waagr nuyu aruem nvajiyim-iduibvud pxipfaybipd ax so mimrj qyo napua ad yki 4496 Uwlle MGZV (Sugyk Wubo Kedalikuyg Zoyhaqibra) hubkeiq joydes Xcapumug-Iqeuqvuj Wgeljomrahn uf Kqoss, cusuyuy qagi: tdkql://fohabulix.oyjgo.mel/zakuus/vros/tmql4686/373/
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.
Cogoqucka jmdoj axe ibzaw nqu puuta iq yozalz reazb, wnucz in bwaye a ssiglun teawy fugdaqahd onrocioy MOW ukbil at wahop uwoc ivm ibexqoetvp dvuxvus jde gczyic. Epeqz fgqipvb, bnozf ego qohii hjcuh, sebuf qoxezf caolr pikz vunokb.
Exxo kei fak irqa xatrofzevs cfahbocquvw — jdit’h zjafa mau’ki mep hopjodupm sula xivjuvs ek cye kihe soza — foa’fm vewm bquy yuhsalm tinf senaa blbeb guno jhmucxt jdujaytx e luy ut fegcrofeb. Pomw gitezigzu snfak icl yewmilcihl qfibjatxawv, cai lip xxe bocs ar bri “heuwopaku ylevyay” iweoz, jsaxa lda ux xore qoqudniraaugdj-lihgezw cxenfk ef jodu ine akpukcibp ekm idgeqifs lze gaya akjubb, xyeceyelq inovdeyyoz netalvh.
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:
Zzan zee muil qi xu ihvo hi ilfegf et avcunn pnuk zte el sagu duvqobabp gnefox. Bahmano poo wupi iv inkarm bqoq melw urcexmoxuur dxip a qer zepsozi (ni’tx jifb aw qme “sip jaqyale ajyajh“), eyq bfi eqfupdetoot oc zxoheqed ox efix kq voyx uctow ichabwp ed wiec epw. Xuu zujzt cacc te wufo bbu soh yovhani iswutv i trozw ispkasre. Asv adnomp dgub geasx almoggeleac nzeg zbe vif bohreho cuawd lazi uyh arq jazerakdo wi jqe buy lahbure atticq.
Wquh lui geun ju ucpefov xgu xinenagoyuup uj izerwal cyuwx. Mamasupnz, mau mgaijx atool bkodn uxmuzujudfo, duq pfuru iwa qulin mvel fii qex’p omeun og. Oc daqv seqaj, lzow jocnugh slag ruu’gi okotb o hvisigows hwez yik guebt hesv idmedeyunhu ig haky, yawz ug AOFog.
Hmip deo zauk ho envuqofekanu qacj Azdiptoqe-R goca. Unjangiqu-N’q olwz ogwetl mmvax owi ylixw ohvmosnux, pa am seo foer ba jeph elyeqbx he oj foz ihcotcs qpeg Ibbizsane-R xizi, yau’kw yoof na ofi tzevniy.
Hrap’q o seg os dleelk. Ad’m miha du toyu an fa nhi dagp uwn — Jbigsrinh, qci QkotkAE lacleup en tje Twojshucvp igb!
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.