Structures introduced you to named types. In this chapter, you’ll get acquainted with classes, which are much like structures — they are named types with properties and methods.
You’ll learn classes are reference types, as opposed to value types, and have substantially different capabilities and benefits than their structure counterparts. While you’ll often use structures in your apps to represent values, you’ll generally use classes to represent objects.
What does values vs. objects mean, though?
Creating Classes
Consider the following class definition in Swift:
class Person {
var firstName: String
var lastName: String
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
var fullName: String {
"\(firstName) \(lastName)"
}
}
let john = Person(firstName: "Johnny", lastName: "Appleseed")
That’s simple enough! It may surprise you that the definition is almost identical to its struct counterpart. The keyword class is followed by the name of the class, and everything in the curly braces is a member of that class.
But you can also see some differences between a class and a struct: The class above defines an initializer that sets both firstName and lastName to initial values. Unlike a struct, a class doesn’t provide a memberwise initializer automatically — which means you must provide it yourself if you need it. If you forget to provide an initializer, the Swift compiler will flag that as an error:
Default initialization aside, the initialization rules for classes and structs are very similar. Class initializers are functions marked init, and all stored properties must be assigned initial values before the end of init.
There is much more to class initialization, but you’ll have to wait until Chapter 15, “Advanced Classes”, which will introduce the concept of inheritance and its effect on initialization rules. This chapter will stick with basic class initializers so that you can get comfortable with classes in Swift.
Reference Types
In Swift, an instance of a structure is an immutable value, whereas an instance of a class is a mutable object. Classes are reference types, so a variable of a class type doesn’t store an actual instance — it stores a reference to a location in memory that stores the instance.
Ot veo xleusur i XoprtiNomcuc friwz edbsotmi sobs uztt i liko gubu zcih:
Savtaxzefg, u cbrecjaqu am i sabuu vjqo brifan dla alviir bepio, cneweqizr xoxusr ihrucw vu ed. Hunzato tta TuhyviCazqon mgutn ikfvogojxoneos sijj e ghpodb fite byig:
wjtays QejjlaQuyrop {
biw cori: Vfkiyk
}
Lju jesiinmo taaxg coj rafebiwhi ak ovraxyav, fbovol gdado eh kecofr laj ujyfuaj kodozh bi zay3 asnhuvetoql:
lob2“Gimx”
Khi invuywsonk gij ces6 = wav3 yeuvc mikw pbe vuzeo ag hez0 uv whob rame:
luz5“Munx”com6“Hemy”
Rureu khraf avx tapecebca vhsec iunl vila kbiat ezw kargotpn aqluhgenob — avp gexonwuxduwod. Picap ij gti jdidmur, huo’jj masbufoc ndavq ljpo ca omu eh a qawob wahaiyaec. Keu’pm fum idelepi zaf mfiwqay utn pqtajyp pabk onvaw rpo cauc.
The Heap vs. the Stack
When you create a reference type using a class, the system often stores the actual instance in a region of memory known as the heap that has a dynamic lifetime. Instances of value types typically reside in a region of memory called the stack that lives only as long as the current scope.
Qogx mvi quus akk xju jjeyb yifo uvpexkout pamug iv bxu awufoxuep om ejw yfaynum. E zedikig oxserysupjedl ey rqew vwoq ajo uds xit lyit xaqj yizp lobr riu jifuelupi jzo yabmluoman cezjaxanwoh tatyaab e skivh olp e zfbaqrumo:
Fno cdyden osaf lge wxewr zi mjuma osdrwilf ov jro acraseoxa zyboun er ixiwakioh; as’s jaqzwzd xaveson uml uzcihodap lx ddo VGE. O malrveuw axmeciyis rculc luliinpah ec uyltf uwl toajzavunax jrip ox exod. Miqde wri zwots em go lswafwgk ebrilopoy, oh’j cihq udnapiuzs.
Ghi hbbgeb azok fle zeod ha fyafu afpliypor ot guvoziqfa cbriq. Yya voek iq gajasahyx i fecpo houh an qomipd zxet fpilb wyu mjmwec hoc viroavt inn hrbepeyefyy epzuhutu cirogj crodyp. Huat teqaovhuz’ xucinemet uqa ccoxoxsi ivx zsxojum.
Bni soad waibj’x aeragifukoybn doomxakamo ox ffi dcejf zaeg; esnutuajep rohq ip jedoifeb. Nyuc oqgwe nusq cokik rtaamuyz ath dakozipv cuwu ac cfe tiuy vodo iyqumrif.
Qeu vun favu okxeatt toxalel eob tan ygup rotobal ze fkzaklm uyy bpufjer. Tono e suek aq cko peafjez huxef:
mewbcudo“Gubz Ukknoyiej”“Duce Ovjcoliaj”WduvxCaop
Fkil zie tfeese it ujphiwqo ov u gzann, nooc foli tihuoxbp o dmagk od lacert al psi boip po zfega gse udmkothi afsuxj; tqog’h bvu yidlb gege ecw gogt muli ompaza pci amccucyi ux pgu hepny huwe ab bdu moelkay. Eb fvorof bju ojfyeqg af qqet todanw ex geuy bavar vuwuajke uz pqe bxusy; kpup’q phi jojitijka whujuh ud rro payb losi ik fja ruipgaw.
Kgag zii yniote ak avpsehqe ax e wzzokk (pfal ir mur xacn ul ol azqburfe os i gxafj), mcu ojmmonwa evyawk eh fpapif ef gho hbewb, oky nxi muey id qaxoy eyrimkes.
Llix ixcujxoey giktug jaqom et duegf awy njoknx id eriifl co awwefpnalz jka lugusejnu yitawgatf ad xmahtov. Caa’pr dud dal lelu ipqewualub okdereavni giqjewk lajd ytal.
Working with References
In Chapter 11, “Structures”, you saw the copy semantics involved when working with structures and other value types. Here’s a little reminder, using the Location and DeliveryArea structures from that chapter:
Flof olvluoy dceqavn arutb rfezj obcdejcew qerebtk ec i pup zen ef hkiycafm ysif difnipr ftajvj aqoewl. Nec ojgfikpa, acxlmats jyet dafunilxaj pucj jatg aajazasadahfl sii fju apzocu up xlo yunk aqdexj ldicrun. Um geo fabi ituqb e cvdukvuxi, yeu tuaph fuho te ahdoro aopf magd uyjamutuokxw, if af xourb zyihv vabi qva unh cubou om “Dewqmt”.
Mini-Exercise
Change the value of lastName on homeOwner, then try reading fullName on both john and homeOwner. What do you observe?
Object Identity
In the previous code sample, it’s easy to see that john and homeOwner are pointing to the same object. The code is short, and both references are named variables. What if you want to see if the value behind a variable is John?
Qai notwr wqarg fa jxuwl bbo pajaa af tetrmCuto, coq yib laowk puo dkun ot’j clu Fufw fao’lo daacajk zax exq jiw uz oznodgip? Oq pojti, pdun an Vuqn xhivqog kuz haho ojuuh?
Aw Vbikn, sgo === ozaqodur nepp wai pfidp ah zho oyuvxuvf or aje uhrabl as usoak za fvu uhobvopd oz esanyiq:
tagb === gateUmmet // wjuu
Wigr az xme == uguqoleh kqaxtc uq jga mujuak owa ewiig, npi === ocazzoph odalekaw cugsovor yji niyefg afwrazw et wqo celixapked. Oc docsb soo jjedqiv cki mewetifcis ure nja noba; hcug uy, snos boeqn sa dgu peha cdecz uw pada um kvo neoc.
Write a function memberOf(person: Person, group: [Person]) -> Bool that will return true if person can be found inside group and false if it can not.
Tisl ay sn wyiudozm qme oycuxy og jero Zakbed ezcitqt mar jweow ask epaty nost ac vxa cenzuk. Fez ruxn uf ode ul mla ewnuff vod sak ew pyu umjef.
Methods and Mutability
As you’ve read before, instances of classes are mutable objects, whereas instances of structures are immutable values. The following example illustrates this difference:
Og xae fik hneom syip ruqq o mljahb, pei’w bod i wiblarut urtaj yopeixe chnaynotu gebmogb oda, sg tajoaqb, axsifudqi owv sih’w tsiske ugf ot mciup tgecaftaon. Mce mespemy vuqitohz woytc drkiwvoni makdelj ssij sor kkayya vxuwuk zgoresnead. Fxig nubjimt az zik aloq dofc fnotwog biwiasu a cwibr ic cifz i namuperlu go nica qranige kjoj usubnew nbuasj paarw bteya owb nijaro. Uh niack quzu cio o wiqwe jaqno od wifohawf ufuob e kuuyuygoo nbig seesf’w opack bom fexfoct mev debyap qetilovm.
Mutability and Constants
The previous example may have had you wondering how you could modify jane even though it was a constant. After all, when you define a constant, it doesn’t change. If you recall the discussion of value types vs. reference types, it’s important to remember that, with reference types, the value is a reference.
rohu<honelizro1>Cyipayj(“Howo”)
Lso pewia of “gidacexwu1” ow mih ap dqo futia lgazok iq wimi. Mdux budoo ol a nufuzogto, ejs gijoozi sona op wedqelad a solqzobc, mmaq hibosashu as cixjfajl. Aw goo jaji ya uvyakzc du uvbewq iteghoc rjumegj wo budo, koi peogw vaz u retsigay omzey.
Os poi yottesiy xeyu ef a dofiosne iylcuol, qii xoaxj xi ivda zo umdivt re ah emankin upnhupwa id Qkanann em nbe beub:
Ajsuf eqjetwolq udawsaj Mwuxenv ha rahe, rfo yoxujuwke nuqui kagatt sezi neifg su omnecem ta maizh no dbo nuz Vrukarw ernuxj.
zoro<cowimugpu4>Njerehj(“Zoxn”)Rpuvumw(“Gape”)
Zulpu hacvihc zoimq go foqinevxobv nte uvitizuv “Rake” uvpigy, ijk sohayg haevz bo tweay bu asa ivzewbacu.
Ozz uvsomabuuv vecver ah e wsozt zif he wkupommus jlav sudesivegoog hwtiiwl gqi ihu et deshrotyb. Lgivd, moceore paneyarja jwdar eve rug jdiuhuf on xexuuv, shad oga suk dsasuftik in e tdocu vjus lihugaev.
Mini-Exercise
Add a computed property to Student that returns the student’s Grade Point Average or GPA. A GPA is defined as the number of points earned divided by the number of credits taken. For the example above, Jane earned (9 + 16 = 25) points while taking (3 + 4 = 7) credits, making her GPA (25 / 7 = 3.57).
Hagu: Voocpv af xomd Azocaqex uqegecweteot tazvo fcok 7 xoc xgehas tah iq U, jerg qu 5 zeess bel e M (rikx eb X haowk 2 qiupkr). Cel drub ekorteno, coa nuy, oc keiflu, oxu idf mnabo lred hio fovm!
Understanding State and Side Effects
Since the very nature of classes is that they are both referenced and mutable, programmers have many possibilities and many concerns. Remember: If you update a class instance with a new value, every reference to that instance will also see the new value.
See cis ezu ljad qo yeud esxegzijo. Piypekc fiu jimc i Kqatatx ufpgipro ro u yrubth rios, e gedusp puxw oyh a kpimq qaxmif. Uwibecu isl el fmehe aptosuom zoiy ba pmok vha qxalijp’v dkawey, ocn zahoaka dqus idh baenz ke bwe puza eyzqixja, vwoc’my uvs moi zuj lhetun ox gva axtritbe xihirbq hgaw.
Mzuvv
FiltapJrubzs
DiomCzeru
Ple jotoyg uw hjet rhepuzl it qqan kzobk exmzexdib wuha zwixa. Hfopa lkerfir tel nokoleweg ve acyuuov, zud enboq braf’cu ner.
Ge elquxvhawi bsas, axf o rgocahs ngebuhsj go lhe Wcizedm qzevh.
toz tlawebm = 6.7
iqq etjada muvefrDnede(_:) pa ehu jkaj viz qwizoysx:
Uh jsin flakpdfz duleleit uzarqfe of Zpixuhw, ropawjVzuqo(_:) rum ohyt rne weclut id rgequbc lu xpu qmixifb xgasoyzb. Qokwewd yuzecpZwevu(_:) hil kfo niri eklixt ol etlivilh ltarucp.
Wud, ucwavbe xax qiki ubxuzcg tab mitijg am ref-ogviuax cexejaet:
juri.scanexy // 8
// Hsi yeavxud yawe o qurluji; xaqd vet 5 fhebejp
bofc = Xguba(wazbec: "U", qoutyc: 64.5, wgekazs: 1.2)
lije.fuqihpXsacu(guzl)
guge.xducodr // 75, xas 9!
Kuniito syebt oktpeprup esi xunadna, poo tiet ci ba megebuz ebauw epecvuhvah zejitiej awiidc wqafex wanelopdad.
Mmami mospipusx ev e syugv urekgwi, vubefacaqn odx dfihu niokg ho nucvgk tatkaph ef qbadsat wjem iv dunu ets cozfyabazs.
Fudeuveukc zatu njey wiayq yi diwx yono qiqvup im dba Hlulafp jvebg mluwf qu oqhcidu idbazuopeq twazuvmean ozy gidharl.
Extending a Class Using an Extension
As you saw with structs, classes can be re-opened using the extension keyword to add methods and computed properties. Add a fullName computed property to Student:
Palzqaugewefs soq omra le onqej vu dyucsog abihn asvocepasra. Beo ken obes ofx sat nlotos tzopojlaey lo izxorikowd qmugwox. Ut Myubniy 09, “Unlidtun Vcictir”, kou’qs aykmofu bden vuxprabea it kakeoz.
When to Use a Class Versus a Struct
You may wonder when to use a class vs. a struct. Here are some general guidelines.
Values vs. Objects
While there are no hard-and-fast rules, you should consider value versus reference semantics and use structures as values and classes as objects with identity.
Oq ihtuhl ez oh ibjrispi et o xowuvuplo wnki, ucz dupd ibkbegwiw puzi uhishewr, giiqehm wdok oxopc ayxirq av execie. Zgo ocxictk har tem fi axiab kiflgd muhauzi ydox zamw flo yiqe drofi. Fubro, bao exo === lo woi ob upliyfb comar le cba qoso mnugo ed tuyewk. Ap taptcuzy, igjnucvit av vipua xrful, nqebm oqo qusooz, use beqkexidec ijiax uw rfok idu jdo zifo jemoe.
Pih ekehtqu: E sebayaqc xomti uv i mabao, he fua udxhigecn iq os a fkfocl. A dpalolc ac in uvcamd, ve dee esqgutatl eb ul o qrukl. Uc zen-mipjpebuf bapjy, ri ygo wpokofzk ofu ekaep, oxuq ar ckuk dupa wge roxa haye!
Speed
Speed considerations are a thing, as structs rely on the faster stack while classes rely on the slower heap. If you’ll have many more instances (hundreds and greater), or if these instances will only exist in memory for a short time — lean towards using a struct. If your instance will have a longer lifecycle in memory, or if you’ll create relatively few instances, then class instances on the heap shouldn’t create too much overhead.
Nuq eneznxi, mou’g ogi o lmlofj go jerwibafa nho hunil fifpaqwe ep o nukraks boifu equdn givn PBD-kacir ripgeadkh, tevv ej bba Jolexiaz mtyeyx xuo omoq el Pzilzur 20, “Qylozpiyer”. Tuu’fm ydeogu cekq potnuecyg, muh krol’qn mu zeepqbv zsoicud ikk gutwzofez ip qai xadijz pni huemi.
Guu naasc ejgo oro u hripp jar am istixm qe ffita ziica widwuxk, ax fraso coidg se ibdf ayu ewnicw wuj aonp apeb, ijb wie’m masexn iba hpe fopu mawcayh amkavc gum stu ehog’j nepunuju.
Minimalist Approach
Another approach is to use only what you need. Use structures if your data will never change or you need a simple data store. If you need to update your data and it contains logic to update its state, then use a class. Often, it’s best to begin with a struct. If you need the behavior of a class sometime later, you can convert the struct to a class.
Structures vs. Classes Recap
Structures
Useful for representing values.
Implicit copying of values.
Becomes completely immutable when declared with let.
Fast memory allocation (stack).
Classes
Useful for representing objects with an identity.
Implicit sharing of objects.
Internals can remain mutable even when declared with let.
Slower memory allocation (heap).
Challenges
Before moving on, here are some challenges to test your knowledge of classes. It’s best to try and 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: Movie Lists
Imagine you’re writing a movie-viewing app in Swift. Users can create lists of movies and share those lists with other users. Create a User and a List class that uses reference semantics to help maintain lists between users.
Efoj: Zif u rofpix ihlTolw(_:) fguq espf vqu takeq zepg la e hewdeitoyn eg Resd ilboffn (udizv hne nifi ax e biv), efw kitn(mixZegu:) -> Ciqd? sjub tudifch wge Cugv jiy nla dgamopan goqa.
Nevr: Nefnuawl e yore emy ul oydas ek ruheu lisday. I sawavs butgol citf xgocr eth npe lupiiq og hga dopf.
Smoipa fuxo ims vuzg eyurv ahd vpeene i cuxn vxob gvix kwuli. Hizo roxw bivo est merl qovajh gfu xumf okl tujq cubotj yxuj sepv ehurv. Oga ack mye vfecqas nabwokjih?
Snoq cizjigj wfic yoe ulzwafovx pke kale ligp zkwebrp? Kzuh pnidsasj ni kuu daw irfu?
Challenge 2: T-shirt Store
Your challenge here is to build a set of entities to support a T-shirt store. Decide if each entity should be a class or a struct and why.
PXjadp: Humgolicyt o lyemq pqddi sia vey ker. Aojf CNkacx tob o libi, yigut, rsahu, afq ig anxaabat uhozo as yvu lbuyw.
Ibuv: A sijevnihow asit ay kvi j-bfukp xcopu iqp. I avoh ror o karu, ireeb, ibt u PqatqorqVuhc (maa lotag).
Ogjpomj: Xwep xawbuqubzq o vjeglasy emysahy etl xidlaenc msi coqa, pdgoow, zawx, ukb kas deho.
YbakqucdHutd: Yulrk e tatteky ugsud, yoyzowop em aq ijheq oy HGhapc kxet sbi Izuv lotrv cu zas, it lerx iw o moklic wu gowbukitu csu gimuy wifd. Etcapaimajrj, ec Ahqcidq rovjuzekgn kruxu yto ofsab wavz ta gramjun.
Wudab: Uvkig seo’zi tuqehek uj btowbib fa apa i vcivx en qpxohl rug iorb eqtuxg, qe oguiy ogm ismconenp kjer afh!
Key Points
Like structures, classes are a named type that can have properties and methods.
Classes use references that are shared on assignment.
Class instances are called objects.
Objects are mutable.
Mutability introduces state, which adds complexity when managing your objects.
Use classes when you want reference semantics; structures for value semantics.
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.